- Home /
Snappy RTS/MOBA/Diablo style Click-to-move character movement
I'm trying to create a Diablo style project and I'm learning from the Survival Shooter sample project, but I'm having problems getting it work correctly. These are the movement conditions I'm trying to get working: Movement command instantly turns character towards hitpoint Movement command cancels and overrides existing commands Spam clicking in different directions close to the character should make the character instantly turn to clicked directions with no braking, turn/rotation animation or delay of any kind.
Purely using navmeshagent.destination, I get slow turns and braking when clicking new locations. I can get the kind of movement I want if I simply use charactercontroller.SimpleMove(transform.forward), but then I obviously have no obstacle avoidance. Any suggestion on what to do?
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI;
namespace CompleteProject {
public class ClickToMove : MonoBehaviour
{
public float stopbefore = .25f;
public float shootDistance = 10f;
public float shootRate = .5f;
public PlayerShooting shootingScript;
private Animator anim;
private CharacterController controller;
private UnityEngine.AI.NavMeshAgent navMeshAgent;
private Transform targetedEnemy; //stores targeted enemy location so player can move towards them
private Ray shootRay; //check if we have hit enemy
private RaycastHit shootHit; //store information about what we hit, beyond a simple bool
private bool walking; //control walk animation on/off
private bool enemyClicked; // t/f clicked on enemy instead of ground
private float nextFire; // based on AS, can we attack again (yet)
private bool autobreak = false;
// Use this for initialization
void Awake()
{
anim = GetComponent<Animator>();
navMeshAgent = GetComponent<NavMeshAgent>();
controller = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // pass a ray from mousePos into the scene
RaycastHit hit;
if (Input.GetButtonDown("Fire2"))
{
// Debug.Log(navMeshAgent.remainingDistance);
// Debug.Log(navMeshAgent.destination);
if (Physics.Raycast(ray, out hit, 1000))//store hit info in out hit. instead of just returning bool, additional info is returned
{
transform.LookAt(hit.point);
if (hit.collider.CompareTag("Enemy"))
{ //check if obj tag = Enemy
targetedEnemy = hit.transform; // set enemy variable to the transform of enemy you clicked on
enemyClicked = true;
}
else
{
walking = true;
enemyClicked = false;
navMeshAgent.isStopped = false;
// Create a vector from the player to the point on the floor the raycast from the mouse hit.
Vector3 playerToMouse = hit.point - transform.position;
// Ensure the vector is entirely along the floor plane.
playerToMouse.y = 0f;
// Create a quaternion (rotation) based on looking down the vector from the player to the mouse.
Quaternion newRotatation = Quaternion.LookRotation(playerToMouse);
// Set the player's rotation to this new rotation.
Quaternion.SlerpUnclamped(transform.rotation, newRotatation, 100);
//playerRigidbody.MoveRotation (newRotatation);
controller.SimpleMove(transform.forward);
navMeshAgent.destination = hit.point;
Debug.Log(navMeshAgent.destination);
}
}
}
/*
if (navMeshAgent.remainingDistance <= navMeshAgent.stoppingDistance)
{
if (!navMeshAgent.hasPath || Mathf.Abs(navMeshAgent.velocity.sqrMagnitude) < float.Epsilon)
Stopall();
}
else
{
walking = true;
}
*/
if (enemyClicked)
{
MoveAndShoot();
}
if ((navMeshAgent.remainingDistance < stopbefore) && (autobreak))
{
Debug.Log("Called");
Stopall();
}
Debug.Log("remain distance " + navMeshAgent.remainingDistance);
//Debug.Log(navMeshAgent.destination);
anim.SetBool("IsWalking", walking);
}
private void Stopall()
{
navMeshAgent.isStopped = true;
navMeshAgent.ResetPath();
}
private void MoveAndShoot()
{
if (targetedEnemy == null)
return;
navMeshAgent.destination = targetedEnemy.position;
if (navMeshAgent.remainingDistance >= shootDistance)
{
navMeshAgent.isStopped = false;
walking = true;
}
if (navMeshAgent.remainingDistance <= shootDistance)
{
transform.LookAt(targetedEnemy);
Vector3 dirToShoot = targetedEnemy.transform.position - transform.position;
if (Time.time > nextFire)
{
nextFire = Time.time + shootRate;
shootingScript.Shoot(dirToShoot);
}
navMeshAgent.isStopped = true;
walking = false;
}
}
}
}
Answer by hexagonius · Dec 17, 2018 at 08:11 PM
A NavMeshAgent has an updatePosition and updateRotation setting that can completely disable the auto workings of them. then you have full control over the agent.