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. Dismiss Notice

Question Rotating around an object using CharacterController.Move in a perfect circle?

Discussion in 'Scripting' started by Delybird, Aug 6, 2023.

  1. Delybird

    Delybird

    Joined:
    Jan 26, 2016
    Posts:
    3
    I'm working on a game with a Zelda OOT style targeting system. Everything has been great but I'm stuck on getting the character to rotate perfectly around the target in a circle.

    My current setup is having the character always face the target with a transform.rotation = quaternion.lerp while moving the character with charactercontroller.move(newdestination). This mostly works however the character obviously doesn't move in a perfect circle, he takes a step directly left or right and then rotates to face the target.

    If you run around a target in a circle, you slowly get further away from them.

    I know there are options like rotatearound build into unity but I noticed the parameter for this is degree per second. I don't think this would work as I want the rotation to match the player's normal movement speed regardless of the distance between the player and the target.

    Any ideas or features that I'm missing?
     
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,588
    We actually have a few similar threads already, which you can check out for more detail. You should stumble upon a bunch when searching anything from "zelda targeting" to "move/orbit around enemy". The short version is that you can use the cross product between the direction towards the target and Vector3.Up to move around it. You will also find a few example implementations of similar systems when googling along the lines of "unity combat lock on". Keep in mind that nothing you find will work exactly as you want it to, so you'll have to adjust as needed. But those are usually good starting points.
     
    Delybird likes this.
  3. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    If you're looking for more in depth reasoning, you just have to understand how transforms work each frame. Now a particular instance I did was have player.rotation have a "LookAt" method which handled rotation. Then I had a set distance that player should be from target, and the code constantly checked that set distance(modify by vertical Input), and would move the player forward or backward to keep that set distance, as I would strafe left or right.

    So imagine, each frame you are saying rotate this much, and move to this position, which both are very small movements. So if each frame isn't "technically" pulling it's weight, you will go more left(further away), and not make a complete circle.

    But as Yoreki states, there more than likely are better methods than the one I used, so definitely look into those. As if you asked for snippets of my methods, people would probably laugh at me, lol :rolleyes:
     
  4. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    510
    Code (CSharp):
    1.         Vector3 offset=(transform.position-enemy.position).normalized*distance;
    2.         destination=enemy.position+Quaternion.Euler(0,-Input.GetAxis("Horizontal")*10f,0)*offset;
    3.         cc.Move((destination-transform.position)*speed*Time.deltaTime);
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    This is because of how discrete physics works: if you're standing on a circumference looking at the center and go pure right or left, obviously you will now be slightly further away from the origin. Put your finger on the edge of your coffee cup right now and see.

    The effect gets vanishingly smaller the smaller the step distance is as the tangent of the intended orbit nears your lateral approximation... you know, standard calculus commentary about d/dx as dx approaches zero.

    You can hack it by noting the distance from center and re-asserting that distance after each move, but of course now you introduce a slightly different rate-of-orbiting error, as that's not truly the correct solution either.

    I would imagine the best fidelity of simulation would be to "back out" the entire orbiting process into some kind of parametric position generation: steadily change your angle and use sin/cos to recompute the offset from center.

    I would just hack it. :)
     
    Yoreki likes this.
  6. Delybird

    Delybird

    Joined:
    Jan 26, 2016
    Posts:
    3
    Thank you for your insight. At the moment the SIN/COS method is what I'm attempting to research and see if I can determine the best way to handle the rotation relative to the distance from the target.
     
  7. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    Take a look at my answer on this post: https://forum.unity.com/threads/how-to-quaternion.1484598/#post-9252075
    Also a little further down, Spiney gave another way to do it, but I feel your problem is related to that one, so take a look and see if anything helps from that post's answers. :)