Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

How To Make Objects Move With Fluid Movement

Discussion in '2D' started by coder_for_life22, May 27, 2016.

  1. coder_for_life22

    coder_for_life22

    Joined:
    Dec 25, 2013
    Posts:
    46
    Hey guys,

    I am building a project that requires enemies to move in a fluid motion.

    They should be able to move in any direction, up, down, diagonal up left, diagonald down left,etc.

    The enemies need to move in fluid motion.

    Right now I have an AI script that moves the fish in any direction but the movement is somewhat choppy when the enemy decides to change directions. I want it to operate somewhat as a AI would. The enemies can wander anywhere they please. The only restrictions are walls.

    This is also a physics based game. Not sure if the plug-in i've listed below moves physic items. I heard it is not good to move objects by transform when using physics.

    Anyone know of any good AI plug-ins I can use for this?

    It is 2D by the way. Right now I am looking into this plug-in: any thoughts?
    https://www.assetstore.unity3d.com/en/#!/content/15277

    Please let me know your thoughts or if you have any other recommendations on options or plug-ins you have tried.

    Thanks!
     
  2. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    If your game is using Physics, then move your enemies using AddForce within FixedUpdate, and give their rigidbodies a linear drag value. That will give them smooth movement.
     
  3. coder_for_life22

    coder_for_life22

    Joined:
    Dec 25, 2013
    Posts:
    46
    The issue is. I want to have a smooth transition between the first velocity of the object and the second. For example, I initially set the first velocity and it moves then a few seconds later I make the object move in a diagonally path by changing its x and y velocity. The issue is. The movement is somewhat chopoy when I switch velocities and a choppy jerk when the velocity suddenly changes. I would like to make it look more fluid and natural by making it gradually change velocity on x and y until it reaches it's full velocity that was set by me. Until it changes again and then rinse repeat.
     
  4. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    That is exactly what AddForce will give you. Put this on an object, set the acceleration and deceleration in the inspector and move it with WASD:

    In your game instead of using Input Axes, use your AI direction vector as the "input" vector.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [RequireComponent(typeof(Rigidbody2D))]
    4. public class PhysicsMovement : MonoBehaviour {
    5.  
    6.     public float acceleration;
    7.     public float deceleration;
    8.  
    9.     private Rigidbody2D physics;
    10.     private Vector2 input;
    11.  
    12.     public void Start() {
    13.         physics = GetComponent<Rigidbody2D>();
    14.         physics.gravityScale = 0;
    15.         physics.drag = deceleration;
    16.     }
    17.  
    18.     public void Update() {
    19.         input.x = Input.GetAxis("Horizontal");
    20.         input.y = Input.GetAxis("Vertical"));
    21.     }
    22.  
    23.     public void FixedUpdate() {
    24.         physics.AddForce(input * acceleration * Time.deltaTime, ForceMode2D.Impulse);
    25.     }
    26. }
     
    Last edited: May 27, 2016
  5. coder_for_life22

    coder_for_life22

    Joined:
    Dec 25, 2013
    Posts:
    46

    Ah I see. But how do I know how much force to apply at a body to move in in a certain direction? Since the force will be applied randomly.
     
  6. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    If you have the direction vector, then you can do "direction * speed" to get the force needed to move in that direction. I did that in the example class, using "input" as my direction vector.

    If your direction vector isn't normalized (vector length of 1), or you're not sure, use the ".normalized" property on the vector when using it as a direction, this will make sure the vector length will equal 1, and won't mess with your speed value when you multiply. (see below for syntax)

    If you want to find a random direction, you can use "UnityEngine.Random.insideUnitCircle", which will give you a random normalized Vector2 (length of 1) to use as a direction.

    Here's the same example class which gets a random direction to move in at the start:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [RequireComponent(typeof(Rigidbody2D))]
    4. public class PhysicsMovement : MonoBehaviour {
    5.  
    6.     public float acceleration;
    7.     public float deceleration;
    8.  
    9.     private Rigidbody2D physics;
    10.     private Vector2 direction;
    11.  
    12.     private void Start() {
    13.         physics = GetComponent<Rigidbody2D>();
    14.         physics.gravityScale = 0;
    15.         physics.drag = deceleration;
    16.  
    17.         direction = UnityEngine.Random.insideUnitCircle;
    18.     }
    19.  
    20.     private void FixedUpdate() {
    21.         Vector2 directionalForce = direction * acceleration;
    22.         physics.AddForce(directionalForce * Time.deltaTime, ForceMode2D.Impulse);
    23.     }
    24. }
    If you want the object to move towards another object, you can get that movement direction by doing:
    Code (CSharp):
    1. (otherObjectPosition - thisObjectPosition).normalized
    and using that vector in your "direction * speed" calculation.

    So with that you should be able to see how you can either move randomly, or move towards a checkpoint or target of sorts.

    Also just a tip, you can use these shorthands to get normalized cardinal directions:
    Vector2.right, Vector2.left, Vector2.up, Vector2.down.

    These are equivalent to Vector2(1,0), Vector2(-1,0), Vector2(0,1), Vector2(0,-1), respectively.
     
    Last edited: May 27, 2016
  7. coder_for_life22

    coder_for_life22

    Joined:
    Dec 25, 2013
    Posts:
    46

    Awesome. So now how would I rotate the object to move in the direction that was randomly selected form the unity circle. how do I go about getting the angle the object is moving in, in order to make the object face that angle?
     
  8. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    If you want to rotate the object so that its X Axis points in the direction of movement, you can do something like this:

    Code (CSharp):
    1.  private void LateUpdate () {
    2.     // get a rotation that points Z axis forward, and the Y axis in the movement direction
    3.     Quaternion newRotation = Quaternion.LookRotation(Vector3.forward, movementDirection);
    4.  
    5.     // apply new rotation
    6.     transform.rotation = newRotation;
    7.  
    8.     // rotate 90 degrees around the Z axis to point X axis instead of Y
    9.     transform.Rotate(0, 0, 90);
    10. }
    The reason for the extra rotation is that "LookRotation" takes parameters for Z axis and Y axis for 3D orientation, but for 2D we need Z axis and X axis, so rotating an additional 90 degrees will offset the result to work for 2D.