- Home /
How can I adjust my position to a specific point after rotating?
Hello, I have a player that moves on the platform and rotates 90 degree when it collides with a bend. After it passes the bend, it must continue moving from the middle of the next platform. I could set its position manually but I don't want it to teleport. I have tried to reach the middle by changing player's rotating speed but it is pretty hard to find the "perfect" speed. I want to know if there is a proper way to do this ? Thank you.
It must rotate like this after rotating. When i increase rotation speed it continues moving like this. I want to keep distances between edges equal and independent from rotation speed. How can I achieve it ?
Here I have a video that shows how it goes out of the middle of the platform: https://files.fm/f/w9bdcswtn
Movement Controller:
public class PlayerMovementController : MonoBehaviour
{
[SerializeField] private ScriptablePlayerMovementSettings _movementSettings;
private Rigidbody rb;
private void Awake()
{
Initialize();
}
private void Initialize()
{
rb = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
Move();
}
private void Move()
{
Vector3 movement = transform.forward * _movementSettings.MovementSpeed * Time.fixedDeltaTime;
rb.MovePosition(transform.position + movement);
}
}
Rotation Controller:
public class PlayerRotationController : MonoBehaviour
{
[SerializeField] private ScriptablePlayerRotationSettings _rotationSettings;
private float _direction = 0;
public float Direction { get => _direction; set => _direction = value; }
private Vector3 _lastRotation = Vector3.zero;
private void Update()
{
if (Direction != 0)
Rotate();
}
private void Rotate()
{
PlayerManager.Instance.PlayerState = PlayerState.Rotating;
Vector3 targetRotation = GetLastRotation() + Vector3.up * Direction * 90f;
targetRotation = new Vector3(targetRotation.x, targetRotation.y % 360, targetRotation.z);
transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.Euler(targetRotation), _rotationSettings.RotationSpeed * Time.deltaTime);
if (transform.eulerAngles.Equals(Quaternion.Euler(targetRotation).eulerAngles))
{
SetLastRotation();
Direction = 0;
PlayerManager.Instance.PlayerState = PlayerState.Normal;
}
}
private void SetLastRotation()
{
_lastRotation = transform.rotation.eulerAngles;
}
private Vector3 GetLastRotation()
{
return _lastRotation;
}
}
I get the direction value based on bend type:
public class PlatformCollisionManager : MonoBehaviour
{
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.GetComponentInParent<PlayerRotationController>() != null)
{
PlayerRotationController playerRotationController = other.gameObject.GetComponentInParent<PlayerRotationController>();
playerRotationController.Direction = (GetComponentInParent<MiddlePlatformMono>().GetPlatformType == PlatformType.TurnLeft) ? -1f : 1f;
}
}
}
Answer by sy1997_unity · Nov 08, 2021 at 08:17 PM
Thanks for the answers. I just solved it by using RotateAround. I detect collision when it hits the platform and start rotating.
private void Rotate()
{
PlayerManager.Instance.PlayerState = PlayerState.Rotating;
Vector3 targetRotation = PlayerHelper.GetCurrentRotation() + Vector3.up * Direction * 90f;
targetRotation = new Vector3(targetRotation.x, targetRotation.y % 360, targetRotation.z);
transform.RotateAround(RotationPivotPoint.position, Vector3.up * Direction, _rotationSettings.RotationSpeed * Time.deltaTime);
if (Mathf.Abs(transform.eulerAngles.y) <= 270f)
{
transform.eulerAngles = targetRotation;
PlayerHelper.SetCurrentRotation(transform.rotation.eulerAngles);
Direction = 0;
PlayerManager.Instance.PlayerState = PlayerState.Normal;
}
}
I take corner of the bend as rotation pivot point and move my player around it. If it reaches 90 or -90 degree, it stops rotating. There is still 0.0002 ~ 0.0004 gap from middle of the platform but it is acceptable for me.
Answer by MarekRimal · Nov 05, 2021 at 04:35 PM
Hi, I think it would be really hard to figure out the perfect rotation.
I would generate a path as a sequence of points and then make the player move the path. The turn is actually a quarter circle. So the approach is to generate points on the quarter circle and make the player go through all these points while looking on each points he is going to.
I made some quick code for you.
// This will generate 90 degree turn to the right
// The resolution smoothens the turn
List<Vector3> MakeRightTurn(float radius, int resolution)
{
List<Vector3> positions = new List<Vector3>();
float t = 0;
float step = 0.5f * Mathf.PI / resolution; // We are making only one quadrant of the circle so 0.5f instead of 2.0f
for (int i = 0; i <= res; i++)
{
float x = radius * Mathf.Sin(t);
float z = radius * Mathf.Cos(t);
Vector3 pos = new Vector3(x, 0, z);
positions.Add(pos);
t += step;
}
return positions;
}
// This will generate 90 degree turn to the left
// The resolution smoothens the turn
List<Vector3> MakeLeftTurn(float radius, int resolution)
{
List<Vector3> positions = new List<Vector3>();
float t = 0;
float step = 0.5f * Mathf.PI / resolution;
for (int i = 0; i <= res; i++)
{
float x = radius * Mathf.Sin(t);
float z = radius * Mathf.Cos(t);
Vector3 pos = new Vector3(x, 0, -z); // To make left turn we just make the z negative
positions.Add(pos);
t += step;
}
return positions;
}
void Start()
{
// This will make player do right turn
MovePlayer(MakeRightTurn(1, 10));
}
void MovePlayer(List<Vector3> positions)
{
// Go throught each point
for(int i=0; i<positions.Length; i++)
{
float threshold = 0.001f
Vector3 dir = (positions[i] - transform.positions).normalized;
transform.LookAt(positions[i]);
// Move player untill he is on the destination point
while(Vector3.Distace(transform.positions, positions[i]) > threshold)
{
transform += dir * speed * Time.deltaTime;
}
}
}
I didnt run the code but I think this approach should work. Like this you can assemble the whole path for the player. If you have any questions, you can ask.
You can either make the whole player movement like this by adding straight paths between these turns as a sequence of two points.
Or you can make the player do these turns after he hit some collider as you had it before.