What I want to achieve is :

  • I have a 3D game - with player in third person - and using cinemachine Camera - imagine it like PUBG where you can look any where - the direction of the player does not change until the player is moving - the direction of character change in the same direction as camera

  • I want to make some sort of Shadow character as enemy , it will face the player - and mimic every movement exactly - not harmful

  • so when the player move forward - the other copy also move toward player - thus blocking his movement

so I want to achieve this using RigidBody - as Physics is needed to solve this puzzle

enter image description here

I tried different approaches- until I got to this code - it works OK - until I change the camera direction and then every thing is not working any more

     public Transform cam ;
    float speed = 10f;    //How fast the player can move
    float turnSpeed = 100;    //How fast the player can rotate
   public Animator animator; //Animation Control
    Rigidbody rigidBody; //Make sure you have a rigidbody
    void Start()
        //Initialize appropriate components
        animator = GetComponent<Animator> ();
        rigidBody = GetComponent<Rigidbody>();
        cam = Camera.main.transform;
    //No need for update function right now, physics work better in Fixed Update
    void FixedUpdate()
        //right is shorthand for (1,0,0) or the x value            forward is short for (0,0,1) or the z value 
        Vector3 dir =  (-cam.forward * Input.GetAxis("Vertical"))+ (cam.right * Input.GetAxis("Horizontal")) ;
        dir.y = 0;//Keeps character upright against slight fluctuations
        if (Input.GetAxis("Horizontal") != 0 ||Input.GetAxis("Vertical") != 0)
                                                   //rotate from this /........to this............../.........at this speed 
            rigidBody.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation (dir), turnSpeed * Time.deltaTime);
            rigidBody.velocity = transform.forward * speed;
            animator.SetFloat ("Blend", 10);//Walk or run Blend works well here
        } else
            rigidBody.velocity = new Vector3(0,0,0).normalized;
            animator.SetFloat ("Blend", 0);//Idle Blend works well here

Use Vector3.Reflect(...) function to get a movement vector for the enemy that is a reflection of the player's movement vector.
First argument of the function is your player movement vector, in your case it should be rigidBody.velocity.
The second argument is a vector that represents the normal of the plane from which the player's vector will be reflected. You'll need to decide what will be the 'mirror' plane for the reflection and use a vector that points out from the mirror plane.
I think you could use a direction vector that points from the enemy to the player as the mirror normal vector, so the enemy's movements won't depend on neither the camera direction nor the direction the player's model is looking at.
So, something like this:

Vector3 dirToPlayer = player.position - enemy.position;
dirToPlayer.Normalize(); // the normal vector should have magnitude 1 so the distance between the enemy and the player won't affect the reflection results.
Vector3 reflectedVector = Vector3.Reflect(playerRigidBody.velocity, dirToPlayer);
enemyRigidBody.velocity = reflectedVector;
  • \$\begingroup\$ Awesome, exactly what I needed, Your code works amazing , the only problem is that if I used your calculation to detect the direction to Player , this makes the enemy always return to meet the player even though he might be not Aligned anymore- I guess this is because I didn't explain the purpose fully of this script - so this is perfect if you want to make mirror like area , but for my need as puzzle I changed the dirToPlay with vector3 represent the plane I need. also this code doesn't make the enemy change the rotation , but it is way much hilarious like this and i really love it ,Thank you \$\endgroup\$ – Islam Ahmady Apr 29 at 22:32
  • \$\begingroup\$ the Code I used if any one need it : Vector3 reflectedVector = Vector3.Reflect(PlayerRigid.velocity, new Vector3(1,0,0)); rigidBody.velocity = reflectedVector; if(rigidBody.velocity.magnitude > 0){ animator.SetFloat ("Blend", 10);//Walk or run Blend works well here }else{ animator.SetFloat ("Blend", 0);//Idle Blend works well here } \$\endgroup\$ – Islam Ahmady Apr 29 at 22:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.