Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by nastaranarasteh · Sep 21, 2021 at 10:25 PM · rigidbodyrandomsmoothmovetowardsmultiple objects

What's the best move/rotate method to simulate a herd of animals moving around?

Since there are so many different methods of moving and rotating gameObjects in Unity, I can't decide which one to use for this specific purpose without having too much performance cost.

I have 20-30 gameObjects that I want to keep moving towards random targets (at random directions) until they either reach the target or collide with another object at which point they get a new random target, smoothly turnand start moving towards it.

I believe that I definitely have to use non-kinematic rigidbodies and freeze their X and Z rotations, but I can't decide which rigidbody methods I should use?!

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Captain_Pineapple · Sep 22, 2021 at 01:51 PM

Hey and welcome,

mostly there is no real best way to do X. However in your case i'd suggest the following:

Since you do not want to have physics based interactions between your animals and their environment (except for collisions) you should make them kinematic. Then use GetComponent().MovePosition(). For rotations MoveRotation(...). Why these functions? because with this (if called properly in FixedUpdate) you will get proper collision interactions. Just setting a transforms position/rotation will not give you the same result.

The last thing you should do for performance optimzation is cache your Rigidbody reference so that you do not call GetComponent each frame.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image nastaranarasteh · Sep 22, 2021 at 04:47 PM 0
Share

Thanks for answering Captain ;-) I'll share the updates after I write the code and test it.

avatar image nastaranarasteh · Sep 22, 2021 at 06:53 PM 0
Share

This is what I got so far:`

 public class BunnyMovement : MonoBehaviour
 {
     private Animator animator;
     private Rigidbody rb;
     [SerializeField] private Vector3 targetPos;
     [SerializeField] private float linearVelocity = 1;
     [SerializeField] private Vector3 angularVelocity = new Vector3(0, 100, 0);
 
     private void Awake()
     {
         animator = GetComponentInChildren<Animator>(includeInactive: true);
         rb = GetComponentInChildren<Rigidbody>(includeInactive: true);
         animator.enabled = true;
         NewTarget();
     }
 
     private void FixedUpdate()
     {
         if (transform.position == targetPos)
         {
             NewTarget();
         }
 
         if (!IsFacingTarget())
         {
             FaceTarget();
         }
         else
         {
             MoveForward();
         }
     }
 
     private void OnCollisionEnter(Collision collision)
     {
         NewTarget();
     }
 
     private void NewTarget()
     {
         float targetX = Random.Range(-24.5f, -16);
         float targetZ = Random.Range(-26.5f, -19);
         targetPos = new Vector3(targetX, 0, targetZ);
     }
 
     private void FaceTarget()
     {
         Quaternion targetRot = Quaternion.LookRotation(targetPos - transform.position);
         targetRot.x = 0; targetRot.z = 0;
 
         Quaternion step = Quaternion.Euler(targetRot.y * angularVelocity * Time.fixedDeltaTime);
         animator.SetFloat("Turn", targetRot.y);
         rb.MoveRotation(rb.rotation * step);
     }
 
     private void MoveForward()
     {
         Vector3 step = transform.forward * linearVelocity * Time.fixedDeltaTime;
         rb.MovePosition(rb.position + step);
     }
 
     private bool IsFacingTarget()
     {
         Vector3 normalizedDir = (targetPos - transform.position).normalized;
 
         if (Vector3.Dot(transform.forward, normalizedDir) < 0.7f)
         {
             return false;
         }
         return true;
     }
 }

Notes: 1. When rigidbody is marked kinematic, no collision is detected. 2. Even after unckecking isKinematic, object sometimes falls through the ground. 3. The objects never stop turning. alt text

avatar image Captain_Pineapple nastaranarasteh · Sep 22, 2021 at 08:30 PM 0
Share

Fair point, i just checked the collider manual once more (link here)


You cannot use kinematic after all when wanting to detect collisions with static colliders. You will only get collisions with other rigidbodys otherwise. So you will have to uncheck isKinematic and go for FreezeAll Rotation and position in the end.

avatar image
0

Answer by nastaranarasteh · Sep 23, 2021 at 01:34 AM

So, I ended up giving the non-kinenatic rigidbody a constant forward velocity for movement and setting the transform.rotation value directly in a Slerp coroutine for rotation. I also removed

if (transform.position == targetPos) { NewTarget(); }

and only call the NewTarget() method in OnCollisionEnter, now. However, I've discovered that every time OnCollisionEnter is called, I'm getting multiple Target positions, which ends up confusing the object rotation, but I guess I would have to create a new question for that.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Captain_Pineapple · Sep 23, 2021 at 06:00 AM 0
Share

OnCollisionEnter triggers for all colliders you hit. So if there is an object with 3 colliders and you hit them all indipendently you get 3 calls to OnCollision Enter.


Apart from that it might be worth checking if triggers are not more suitable for your case as you don't care for the collision itself either way if i understood that correctly.


But yes, in general -> new questions should be posted as such.

avatar image nastaranarasteh · Sep 23, 2021 at 06:29 AM 1
Share

For anyone out there looking for something like this, here's what I ended up with:

 private Animator animator;
      private Rigidbody rb;
         
      [SerializeField] private Quaternion targetRot;
      [SerializeField] private float speed = 1;
      [SerializeField] private float turnDuration = 2;
      [SerializeField] private bool isTurning = false;
         
      private float lastCheckTime;
      private Vector3 lastCheckPos;
         
      private void Awake()
      {
         animator ??= GetComponentInChildren<Animator>(includeInactive: true);
         rb ??= GetComponentInChildren<Rigidbody>(includeInactive: true);
         if (animator != null) { animator.enabled = true; } 
         TurnTowardsNewTarget();
     }
         
     private void FixedUpdate()
     {
          if (!isTurning  && (Time.time - lastCheckTime) > 2)
         {
                if ((transform.position - lastCheckPos).magnitude < 1)
                {
                     TurnTowardsNewTarget();
                }
                lastCheckPos = transform.position;
                lastCheckTime = Time.time;
        }
        rb.velocity = transform.forward * speed;
    }
         
    private void OnCollisionEnter(Collision collision)
    {
         if (!isTurning) { TurnTowardsNewTarget(); }
    }
         
    private void TurnTowardsNewTarget()
    {
          float yRotation = Random.Range(0, 345);
          targetRot = Quaternion.Euler(0, yRotation, 0);
         
          StartCoroutine(Turn());
    }
         
    private IEnumerator Turn()
    {
        isTurning = true;
        float elapsedTime = 0;
         
        while (elapsedTime < turnDuration)
       {
           transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, elapsedTime / turnDuration);
 
            elapsedTime += Time.deltaTime;
            yield return null;
        }
        transform.rotation = targetRot;
        isTurning = false;
    }
 

Of course it can be manipulated to add more variations to the animals' behaviours.

avatar image Captain_Pineapple nastaranarasteh · Sep 23, 2021 at 11:10 AM 0
Share

thx for sharing your solution

avatar image nastaranarasteh Captain_Pineapple · Sep 23, 2021 at 04:22 PM 0
Share

No problem :-) I'm sure there are better ways to do this, but this is the best I could come up with, with my limited knowledge.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

180 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Smooth look at Random Transform ? 1 Answer

how to use rigidbody.moveposition to go to an exact location 3 Answers

Velocity of multiple rigidbody obiects in array 4 Answers

Does MoveTowards accept Physic Material? 1 Answer

Clone of Coin Doer Game.Need Help 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges