Click to Rotate towards raycast, then Move
Hi there, in a top down click-to-move scenario, I'd like to rotate my Navmesh agent and only after it's rotated towards the target destination should the Navmesh agent move forward (think dota movement).
I'm getting confused on how to do this... Here's my code so far:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class ClickToMove : MonoBehaviour
{
public static ClickToMove instance;
public Camera cam;
public NavMeshAgent agent;
private Vector3 targetPosition;
private Vector3 lookAtTarget;
private Quaternion playerRot;
private float rotSpeed = 55;
void Update()
{
cam = Camera.main;
if (Input.GetMouseButtonDown(1))
{
SetTargetPosition();
}
Move();
}
void SetTargetPosition()
{
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 1000))
{
targetPosition = hit.point;
lookAtTarget = new Vector3(targetPosition.x - transform.position.x, transform.position.y, targetPosition.z - transform.position.z);
playerRot = Quaternion.LookRotation(lookAtTarget);
}
}
void Move()
{
this.transform.rotation = Quaternion.Slerp(transform.rotation, playerRot, rotSpeed * Time.deltaTime);
agent.SetDestination(targetPosition);
}
}
(Any help would be GREATLY appreciated)
Answer by Invertex · Jul 23, 2020 at 12:47 AM
Firstly, use Quaternion.RotateTowards so that your rotation rates are consistent instead of getting slower and slower as it gets closer to the desired rotation.
Secondly, do your agent.SetDestination(targetPosition)
inside the Raycast section so it is only needing to be done when targets change. And also add agent.isStopped = true;
below it.
As for movement, change your Move() method to this:
void Move()
{
if(Quaternion.Dot(transform.rotation, playerRot) < 1)
{ //Dot() returned less than 1, so rotations do not match.
agent.isStopped = true;
transform.rotation = Quaternion.RotateTowards(transform.rotation, target.rotation, rotSpeed * Time.deltaTime);
}
else { agent.isStopped = false; }
}
This way, when target is changing, movement stops. Though if you intend to allow for following a moving target that will cause stutter-stepping so you'll need to change the code to only stop when target manually changed in that case.