diff --git a/Assets/OkapiKit/Scripts/Actions/ActionDash.cs b/Assets/OkapiKit/Scripts/Actions/ActionDash.cs new file mode 100644 index 0000000..7d5c9e8 --- /dev/null +++ b/Assets/OkapiKit/Scripts/Actions/ActionDash.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using Random = UnityEngine.Random; + +namespace OkapiKit +{ + [AddComponentMenu("Okapi/Action/Dash")] + public class ActionDash : Action + { + public enum RelativeTo { Right, Up, LocalRight, LocalUp }; + + [SerializeField] + private Transform target; + [SerializeField, OVNoFunction] + private OkapiValue speed = new OkapiValue(100.0f); + [SerializeField] + private RelativeTo direction; + [SerializeField, OVNoFunction] + private OkapiValue angle = new OkapiValue(0.0f); + [SerializeField, OVNoFunction] + private OkapiValue duration = new OkapiValue(0.1f); + + float timer = 0; + float actualSpeed; + + public override void Execute() + { + if (!enableAction) return; + if (!EvaluatePreconditions()) return; + if (target == null) return; + + timer = duration.GetFloat(gameObject); + actualSpeed = speed.GetFloat(gameObject); + } + + public override string GetActionTitle() => "Dash"; + + public override string GetRawDescription(string ident, GameObject gameObject) + { + string desc = GetPreconditionsString(gameObject); + + if (target) + { + desc += $"Moves object {target.name} "; + } + else + { + desc += "Moves this object "; + } + + switch (direction) + { + case RelativeTo.Right: + desc += "in the right direction"; + break; + case RelativeTo.Up: + desc += "in the up direction"; + break; + case RelativeTo.LocalRight: + desc += "in the local right direction"; + break; + case RelativeTo.LocalUp: + desc += "in the local up direction"; + break; + default: + break; + } + + desc += $", plus {angle.GetDescription()} degrees, "; + desc += $"at a speed of {speed.GetDescription()} units/second, "; + desc += $"for {duration.GetDescription()} seconds."; + + return desc; + } + + protected override void CheckErrors() + { + base.CheckErrors(); + + if (target == null) + { + _logs.Add(new LogEntry(LogEntry.Type.Warning, "Transform to modify is this object, but it should be explicitly linked!", "Setting options explicitly is always better than letting the system find them, since it might have to guess our intentions.")); + } + } + + protected override void Awake() + { + base.Awake(); + } + + protected void FixedUpdate() + { + timer -= Time.fixedDeltaTime; + if (timer > 0) + { + target.position += GetDirection() * actualSpeed * Time.fixedDeltaTime; + } + } + + Vector3 GetDirection() + { + var dir = Vector2.zero; + switch (direction) + { + case RelativeTo.Right: + dir = Vector2.right; + break; + case RelativeTo.Up: + dir = Vector2.up; + break; + case RelativeTo.LocalRight: + dir = target.right; + break; + case RelativeTo.LocalUp: + dir = target.up; + break; + default: + break; + } + + var newDir = Vector2.zero; + var radAngle = Mathf.Deg2Rad * angle.GetFloat(gameObject); + var c = Mathf.Cos(radAngle); + var s = Mathf.Sin(radAngle); + + newDir.x = dir.x * c - dir.y * s; + newDir.y = dir.x * s + dir.y * c; + + dir = newDir; + + return dir; + } + } +}; diff --git a/Assets/OkapiKit/Scripts/Actions/ActionDash.cs.meta b/Assets/OkapiKit/Scripts/Actions/ActionDash.cs.meta new file mode 100644 index 0000000..2b30731 --- /dev/null +++ b/Assets/OkapiKit/Scripts/Actions/ActionDash.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c7d186bd5e292d640a756459bf143ceb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 19123384572852a4daa41848ffb978e7, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/OkapiKit/Scripts/Base/OkapiValue.cs b/Assets/OkapiKit/Scripts/Base/OkapiValue.cs index 72a45a4..74d4c73 100644 --- a/Assets/OkapiKit/Scripts/Base/OkapiValue.cs +++ b/Assets/OkapiKit/Scripts/Base/OkapiValue.cs @@ -16,8 +16,23 @@ public enum Type { Float = 0, Integer = 1, VariableInstance = 2, Variable = 3 }; [SerializeField] private Variable variable; [SerializeField] private float floatValue; [SerializeField] private int intValue; + private float v; - public object GetRawValue() + public OkapiValue(float v) : this() + { + this.init = true; + this.type = Type.Float; + this.floatValue = v; + } + + public OkapiValue(int v) : this() + { + this.init = true; + this.type = Type.Integer; + this.intValue = v; + } + + public object GetRawValue(GameObject go) { switch (type) { @@ -34,6 +49,45 @@ public object GetRawValue() return null; } + public float GetFloat(GameObject go) + { + switch (type) + { + case Type.Float: + return floatValue; + case Type.Integer: + return intValue; + case Type.VariableInstance: + return (variableInstance) ? (variableInstance.GetValue()) : (0.0f); + case Type.Variable: + return (variable) ? (variable.currentValue) : (0.0f); + } + + return 0.0f; + } + + public string GetDescription() + { + switch (type) + { + case Type.Float: + return floatValue.ToString(); + case Type.Integer: + return intValue.ToString(); + case Type.VariableInstance: + if (variableInstance != null) return variableInstance.name; + break; + case Type.Variable: + if (variable != null) return variable.name; + break; + default: + break; + } + + return "[UNDEFINED]"; + } + + public string GetName() { switch (type) diff --git a/Assets/OkapiKit/Scripts/Editor/ActionChangeMovementEditor.cs b/Assets/OkapiKit/Scripts/Editor/ActionChangeMovementEditor.cs index de9e63a..6ce24ba 100644 --- a/Assets/OkapiKit/Scripts/Editor/ActionChangeMovementEditor.cs +++ b/Assets/OkapiKit/Scripts/Editor/ActionChangeMovementEditor.cs @@ -101,8 +101,9 @@ public override void OnInspectorGUI() if (propUseRandom.boolValue) { - EditorGUILayout.PropertyField(propStartAngle, new GUIContent("Start Angle", "What's the minimum angle for the random.")); - EditorGUILayout.PropertyField(propEndAngle, new GUIContent("End Angle", "What's the maximum angle for the random.")); + string localText = (propUseRandom.boolValue)?("local"):(""); + EditorGUILayout.PropertyField(propStartAngle, new GUIContent("Start Angle", $"What's the minimum angle for the random. Angle = 0 means in the direction of the {localText} X axis")); + EditorGUILayout.PropertyField(propEndAngle, new GUIContent("End Angle", $"What's the maximum angle for the random. Angle = 90 means in the direction of the {localText} Y axis")); EditorGUILayout.PropertyField(propSpeedRange, new GUIContent("Speed Range", "The velocity will have a speed between the value in X and the value in Y.")); } else diff --git a/Assets/OkapiKit/Scripts/Editor/ActionDashEditor.cs b/Assets/OkapiKit/Scripts/Editor/ActionDashEditor.cs new file mode 100644 index 0000000..0a548ba --- /dev/null +++ b/Assets/OkapiKit/Scripts/Editor/ActionDashEditor.cs @@ -0,0 +1,55 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using static OkapiKit.ActionDash; + +namespace OkapiKit.Editor +{ + [CustomEditor(typeof(ActionDash))] + public class ActionDashEditor : ActionEditor + { + SerializedProperty propTarget; + SerializedProperty propSpeed; + SerializedProperty propDirection; + SerializedProperty propAngle; + SerializedProperty propDuration; + + protected override void OnEnable() + { + base.OnEnable(); + + propTarget = serializedObject.FindProperty("target"); ; + propSpeed = serializedObject.FindProperty("speed"); ; + propDirection = serializedObject.FindProperty("direction"); ; + propAngle = serializedObject.FindProperty("angle"); ; + propDuration = serializedObject.FindProperty("duration"); ; + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + if (WriteTitle()) + { + StdEditor(false); + + var action = (target as ActionDash); + if (action == null) return; + + EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField(propTarget, new GUIContent("Target", "Which object transform will be moved.\nDashing is just changing the position of an object in a certain way.")); + EditorGUILayout.PropertyField(propSpeed, new GUIContent("Speed Range", "How fast should the object move, in units/second?\nThis is a range, everytime this action runs, a random number will be selected between these two and used as the speed.")); + EditorGUILayout.PropertyField(propDirection, new GUIContent("Direction", "In which direction should the object move? This is the basis from where the direction itself is calculated, using the next property (angle)")); + EditorGUILayout.PropertyField(propAngle, new GUIContent("Angle", "What's the angle of movement, measured from the axis above.")); + EditorGUILayout.PropertyField(propDuration, new GUIContent("Duration", "For how long should the movement happen? If this action is triggered again, it will cancel previous dashes.")); + + if (EditorGUI.EndChangeCheck()) + { + serializedObject.ApplyModifiedProperties(); + (target as Action).UpdateExplanation(); + } + } + } + } +} \ No newline at end of file diff --git a/Assets/OkapiKit/Scripts/Editor/ActionDashEditor.cs.meta b/Assets/OkapiKit/Scripts/Editor/ActionDashEditor.cs.meta new file mode 100644 index 0000000..8f3f174 --- /dev/null +++ b/Assets/OkapiKit/Scripts/Editor/ActionDashEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d51ff6740118b704f920685658c9ebd5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/OkapiKit/Scripts/UI/MultiValueDisplay.cs b/Assets/OkapiKit/Scripts/UI/MultiValueDisplay.cs index 07cb66c..c059691 100644 --- a/Assets/OkapiKit/Scripts/UI/MultiValueDisplay.cs +++ b/Assets/OkapiKit/Scripts/UI/MultiValueDisplay.cs @@ -54,7 +54,7 @@ protected object[] GetVariables() foreach (var v in values) { - vars.Add(v.GetRawValue()); + vars.Add(v.GetRawValue(gameObject)); } return vars.ToArray(); diff --git a/ReleaseNotes.md b/ReleaseNotes.md index c3f906f..0a0275d 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -4,7 +4,7 @@ - Added InputRotatesSprite and VelocityRotatesSprite to Flip Behaviour on platformer controller. Rotating instead of scaling changes the actual objects direction, so it can affect other movement systems, for example. - Movement components can now have conditions built in which take care of activating/deactivating that movement - +- Added Dash action, which enable short bursts of movement, using variables or values ## V1.13.0 diff --git a/Todo.txt b/Todo.txt index 6e9c80e..f87b84b 100644 --- a/Todo.txt +++ b/Todo.txt @@ -1,9 +1,10 @@ Features: --------- -- Unify ValueHandler/Value with single selector that can take any of them +- OkapiValue options for random numbers (floats, integers, with variables as limits) +- Change everything to use OkapiValue instead of actual values +- An option to change values based on reflection - Movement targets should be redefinable -- Replace ranges used for random number generation with a "ValueSelector", which allows a literal, a range and a ValueHandler/Variable. The range can also use ValueHandler/Variable for the limits. - Change numbers in most definitions (conditions, for example) by something that can be either a ValueHandler, a Variable, a literal, or a function, with a property drawer, etc - Add HueShift/Outline effect for sprites - Added debug system to Okapi @@ -17,10 +18,9 @@ Features: - Spawner with boxes should have options for direction - Spawner should have random direction possibility - Path shows direction (debug) -- Target can be collision object (being able to damage another object when there is a collision, for example) - Bool and string variables - Press '+' to add a point at cursor when editing a path -- Add insert option for path +- Add insert point option for path - Probes: - Circle - Box @@ -35,6 +35,7 @@ Usability: - Add triggers/actions directly in the objects - Have the ability to have custom adds (SetVisibility, SetVelocity, etc) - Add node ID property to actions/triggers +- Remove Naughty Attributes completely (reduce dependencies) Simple usage: -------------