- Home /
NGUI and raycasting - the never ending story
Hey! I am currently working on a Game with click-and-go-to-movement but somehow the character is moving also when i am pressing a button of my NGUI ui. Does somebody know how i can solve this issue? here is the movement code (using A* for pathfinding):
using UnityEngine;
using System.Collections;
using Pathfinding;
namespace UniRPG
{
[AddComponentMenu("UniRPG/Character 2/Movement/Aron")]
[RequireComponent(typeof(Seeker))]
[RequireComponent(typeof(Rigidbody))]
public class Chara2_AronNavi : Chara2_NaviBase
{
public LayerMask collisionLayers = -1;
public float slopeLimit = 40f;
public float stopDistance = 1f;
public float stepHeight = 0.3f;
public float waypointDistance = 1f;
public float gravity = 30f;
// Please note that this navigator does not work well with continues calls to MoveTo but a simple move
// fallback can be used if you want player to move while, for example, holding the mouse button down
public bool allowSimpleMove = false;
// ============================================================================================================
private bool grounded = false;
private bool moving = false;
private bool turning = false;
private bool pathing = false;
private Vector3 targetPosition;
private float moveSpeed;
private float turnSpeed;
private Transform _tr;
private Rigidbody _rb;
private Seeker _seeker;
private Vector3 targetDirection;
private Vector3 moveDirection;
private Path path;
private int currentWaypoint = 0;
private Vector3 waypointPosition;
private Vector3 pos;
// ============================================================================================================
public void Awake()
{
_tr = transform;
_seeker = GetComponent<Seeker>();
_rb = GetComponent<Rigidbody>();
_rb.freezeRotation = true;
_rb.useGravity = false;
_rb.isKinematic = true;
}
void OnEnable()
{
path = null;
moving = false;
turning = false;
pathing = false;
_seeker.enabled = true;
}
void OnDisable()
{
path = null;
moving = false;
turning = false;
pathing = false;
_rb.Sleep();
_seeker.enabled = false;
}
public void Update()
{
if (turning)
{
moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, 360f * Mathf.Deg2Rad * Time.deltaTime, 1000);
moveDirection = moveDirection.normalized;
_tr.rotation = Quaternion.LookRotation(moveDirection);
if (Vector3.Dot(_tr.forward, targetDirection) == 0f) turning = false;
}
if (!moving)
{
if (!grounded)
{
RaycastHit hit2;
if (Physics.Raycast(_tr.position + _tr.up * 10f, -_tr.up, out hit2, 100f, 1 << UniRPGGlobal.DB.floorLayerMask))
{
pos = _tr.position;
if (Vector3.Distance(pos, hit2.point) < 0.01f) grounded = true;
else
{
if (pos.y < hit2.point.y)
{
targetPosition.y = pos.y = hit2.point.y;
grounded = true;
}
else
{
targetPosition.y = pos.y = Mathf.MoveTowards(pos.y, hit2.point.y, gravity * Time.deltaTime);
}
_tr.position = pos;
}
}
}
return;
}
if (path != null)
{
if (currentWaypoint >= path.vectorPath.Count) { moving = false; return; }
waypointPosition = path.vectorPath[currentWaypoint];
}
// calculate direction to face
targetDirection = waypointPosition - _tr.position;
moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, turnSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);
moveDirection.y = 0f;
moveDirection = moveDirection.normalized;
if (moveDirection != Vector3.zero)
{
_tr.rotation = Quaternion.LookRotation(moveDirection);
}
// something I can't get over in front of me? Stop.
RaycastHit hit;
if (Physics.Raycast(_tr.position + _tr.up * stepHeight, _tr.forward, out hit, stopDistance, collisionLayers))
{
// ignore triggers
if (!hit.collider.isTrigger)
{
float angle = Vector3.Angle(hit.normal, Vector3.up);
if (angle > slopeLimit) { moving = false; return; }
}
}
// move it
_tr.position = Vector3.MoveTowards(_tr.position, waypointPosition, moveSpeed * Time.deltaTime);
// near enough to target position? Stop.
if ((targetPosition - _tr.position).sqrMagnitude < stopDistance)
{
moving = false;
}
// gravity
grounded = false;
if (Physics.Raycast(_tr.position + _tr.up * 10f, -_tr.up, out hit, 100f, 1 << UniRPGGlobal.DB.floorLayerMask))
{
pos = _tr.position;
if (pos.y < hit.point.y)
{
targetPosition.y = pos.y = hit.point.y;
grounded = true;
}
else targetPosition.y = pos.y = Mathf.MoveTowards(pos.y, hit.point.y, gravity * Time.deltaTime);
_tr.position = pos;
}
if (!moving) return;
if (path != null)
{
// choose next waypoint?
if (targetDirection.sqrMagnitude < waypointDistance)
{
currentWaypoint++;
}
}
}
private void OnPathComplete(Path p)
{
if (!p.error)
{
moving = true;
path = p;
currentWaypoint = 0;
}
else moving = allowSimpleMove;
pathing = false;
}
// ============================================================================================================
public override void LookAt(Vector3 targetPosition)
{
if (moving) return;
this.turning = true;
targetPosition.y = _tr.position.y;
this.targetDirection = targetPosition - _tr.position;
}
public override void MoveTo(Vector3 targetPosition, float moveSpeed, float turnSpeed)
{
this.pathing = true;
this.turning = false;
this.moving = allowSimpleMove;
this.targetPosition = targetPosition;
this.waypointPosition = targetPosition; // something till path is calculated
this.targetDirection = targetPosition - _tr.position;
this.moveSpeed = moveSpeed;
this.turnSpeed = turnSpeed;
this.path = null;
_seeker.StartPath(_tr.position, targetPosition, OnPathComplete);
}
public override void Stop()
{
this.moving = false;
this.targetPosition = transform.position;
}
public override Vector3 CurrentVelocity()
{
if (!moving) return Vector3.zero;
return (moveDirection * moveSpeed);
}
public override float CurrentSpeed()
{
if (!moving) return 0f;
float s = (moveDirection * moveSpeed).magnitude;
if (s == 0.0f) return 0.001f;
return s;
}
public override bool IsMovingOrPathing()
{
return moving || pathing;
}
// ============================================================================================================
}
}
I'm having a difficult time finding the right spot in your code to do this, but essentially what you want is to have a check on the raycast... for example,
//Pardon the pseudo, but I hope it gets the idea across.
if Raycast hit.collider.name == button
//dont move
else
//move
Checking the gameobject name may not be the best way, its the idea I'm trying to point out. You could add a new Layer called Ground, and check if the ray hit Ground, if it did, than can move. This should work because the buttons definitely should not have Ground as their layer.
Your answer
Follow this Question
Related Questions
How do i check if mouse moved a certain distance? 2 Answers
Move to and stop 1 Answer
how can do click then move on a gameobject? 1 Answer
Character Customization Problem, Hard to explain... JS 0 Answers