Using Raycast hit to set vector position then moving player to that position
Hi All,
I know there are many topics on this area however I am yet to find a solution. I'm new to unity, am grasp the logic behind the code OK however am struggling with trying to use Raycast Hit for a none flat terrain.
I've made some small changes to the namimg conventions but apart from that everything is exact from what I can tell.
The SimpleMove function doesn't appear to work. No errors are received when running the script. All the player does is rotate that it. Doen't move from it's position. Have tried using other methods (one is commented out in the below code) but to no avail. Would really like to learn more as I progress through this tutorials. Help very much appreciated.
This method works but I want to use the Raycast hit to detect if it's an enemy or an item I have clicked on.
Have tried playing around with navmesh agents instead where character can move around but can't get the navmesh and raycast hit working. Any help again appreciated.
The code I have below.
void Awake()
{
//anim = GetComponent<Animator>();
}
void Start()
{
targetPosition = transform.position; // will set the target position to our current position on start
}
// Update is called once per frame
void Update()
{
//if the player clicked on the screen, find out where
if (Input.GetMouseButton(LEFT_MOUSE_BUTTON))
{
SetTargetPosition();
}
MovePlayer();
}
void SetTargetPosition() // set position we will travel too
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, 1000))
{
targetPosition = new Vector3(hit.point.x, hit.point.y, hit.point.z);
}
}
void MovePlayer()
{
if (Vector3.Distance(transform.position, targetPosition) > 1)
{
Quaternion newRotation = Quaternion.LookRotation(targetPosition - transform.position, Vector3.forward);
newRotation.x = 0f;
newRotation.z = 0f;
transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, Time.deltaTime * 10);
controller.SimpleMove(transform.forward * walkspeed);
//transform.position = Vector3.MoveTowards(transform.position, targetPosition, walkspeed * Time.deltaTime);
Debug.DrawLine(transform.position, targetPosition, Color.red);
}
}
}
Answer by wibble82 · Dec 21, 2015 at 05:36 PM
Hi
I'm not sure if it could be causing the issue, but to start with your quaternion code is definitely bad! :)
You can not simply set the x/z values of a quaternion. Perhaps you're confusing it with the euler angles (displayed in the inspector)? I suspect what you're trying to do is point the rotation at the target in terms of y rotation, but leave x and z rotation alone? For this, the simplest approach would be to just make your 'target' be at the same z as your transform:
void MovePlayer()
{
Vector3 currentTarget = targetPosition;
currentTarget.y = transform.position;
if (Vector3.Distance(transform.position, currentTarget) > 1)
{
Quaternion newRotation = Quaternion.LookRotation(currentTarget - transform.position, Vector3.forward);
transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, Time.deltaTime * 10);
controller.SimpleMove(transform.forward * walkspeed);
//transform.position = Vector3.MoveTowards(transform.position, targetPosition, walkspeed * Time.deltaTime);
Debug.DrawLine(transform.position, currentTarget, Color.red);
}
}
I'm not sure exactly what the controller.SimpleMove does - presumably you have another script that the controller is referencing, so that could be screwing with your transform. Without knowing more about it I couldn't say though.
All that said, just to be sure, have you made 100% certain that walkspeed is not 0? (just checking!)
-Chris
Thanks. for the suggestion. I tried that but had no luck.
I assume the Simple$$anonymous$$ove is a unity function as the tutorial doesn't point out any other scripts. Only adding the controller as a component to the player.
Have been looking for more information and have decided to go with the nav$$anonymous$$eshAgent to for pathfinding which rules out the problems for now ( will look into disabling nav$$anonymous$$eshAgent rotation (for the player) and speed. I want to set the rotation for the player as the nav$$anonymous$$esh rotation doesn't look good and I eventually want to toggle run or walk.
Now I'm trying to detect if my ray hits another object which is tagged.
void SetTargetPosition() // set position we will travel too
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Plane plane = new Plane(Vector3.up, transform.position);
float point = 0f;
if (Physics.Raycast(ray, out hit))
{
Debug.Log("Is this working?");
if (hit.collider.tag == "Enemy")
{
Debug.Log("we are going to attack!");
}
else if (hit.collider.tag == "Item")
{
Debug.Log("Lets go pick up whatever this is");
}
else if (hit.collider.tag == "Wall")
{
Debug.Log("im going to run into a wall");
Debug.DrawLine(transform.position, targetPosition, Color.red);
}
else if (plane.Raycast(ray, out point))
{
targetPosition = ray.GetPoint(point);
Debug.Log("we are going for a casual stroll!");
Debug.DrawLine(transform.position, targetPosition, Color.green);
}
}
}
void $$anonymous$$ovePlayer()
{
//Quaternion targetRotation = Quaternion.LookRotation(targetPosition - transform.position);
//transform.rotation = targetRotation;
//transform.LookAt(targetPosition);
//transform.position = Vector3.$$anonymous$$oveTowards(transform.position, targetPosition, walkspeed * Time.deltaTime);
agent.SetDestination(targetPosition);
}
}
It can distinguish between where it can walk (casual stroll) and if it will hit a wall using the debug draw line red and green. Having problems with overlapping navmesh (have a 2nd floor with stairs) and looking into that as well.
I'm trying to get the raycast to detect an enemy but i think that problem has more to do with the enemy mesh collider rather than the code functionality.
If you could suggest anything else that I can try on the above point I'll appreciate it otherwise i'll mark this as complete.
Answer by thumper_the_great · Dec 22, 2015 at 02:59 PM
Answer in my comment. Have used navMeshAgent instead for pathfinding wilst still be able to use a Raycast Hit to determine what object i've hit with the raycast