I try my best but my raycast still goes backwards every time - please I need help
Here's my code - basically the code shoots a raycast forward button to detected an enemy but instead the raycast goes the opposite way.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class milkscript: MonoBehaviour
{
NavMeshAgent Agent;
public Transform Point;
public float raydistance = 40f;
public float enemyview = 5f;
// Start is called before the first frame update
void Start()
{
Agent = GetComponent<NavMeshAgent>();
}
// Update is called once per frame
void Update()
{
RaycastHit Hit;
if(Physics.Raycast(Point.position,Point.position + Point.forward, out Hit, raydistance))
{
Debug.DrawRay(Point.position, Hit.transform.forward, Color.red);
Debug.Log(Hit.transform.name);
if(Hit.transform.tag == "chcolatemilk")
{
ChasePlayer(Hit.transform);
}
}
}
public void ChasePlayer(Transform target)
{
Agent.SetDestination(target.position);
transform.LookAt(target.position);
}
}
I think this is a combination of two issues
As mentioned your
Debug.DrawRay(Point.position, Hit.transform.forward, Color.red);
draws the ray in direction of Hit.transform.forward which is not the original direction you shoot your Raycast in
As a direction or the Raycast you are passing in
Point.position + Point.forward
which rather is a position.
You want to pass in only Point.forward as a direction
So it should rather be
void Update()
{
if(Physics.Raycast(Point.position, Point.forward, out var Hit, raydistance))
{
Debug.DrawLine(Point.position, Hit.transform.position, Color.red);
// TODO: remove this later! Logging every frame is quite expensive!
Debug.Log(Hit.transform.name);
// prefer "CompareTag" over "=="! It is a) slightly faster and b)
// instead of failing silently throws an error for typos and non-existent tags => better debugging live
if(Hit.transform.CompareTag("chcolatemilk"))
{
ChasePlayer(Hit.transform);
}
}
Debug.DrawRay(Point.position, Point.forward, Color.green);
}
Related
I am new in Unity and trying to create an Android mobile game.
First, I decided to create a script called "SelectObject" that will move the objects, provided that the object has a collider.
I add this script to the "MainCamera" components, since we need to determine if the camera ray touched the object.
Here is the script "SelectObject":
using UnityEngine;
using System.Collections;
public class SelectObject : MonoBehaviour
{
void Start() {
}
public void Update()
{
if ((Input.touchCount > 0) && (Input.touches[0].phase == TouchPhase.Began)) {
Ray ray = Camera.main.ScreenPointToRay(Input.touches[0].position);
RaycastHit hit; //Declaring the variable hit, in order to further determine if the camera's ray touhed the object
if (Physics.Raycast(ray, out hit)) {
if (hit.collider != null) { //If the ray of camera touches the collider
hit.collider.GetComponent<Move>().Movement(); //Calling the "Movement" method from script "Move" to move the object
}
}
}
}
}
The Move class is a component of the "Cylinder" object that should move when you click on it.
Here is the "Move" class:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour {
public float speedModifier; //Determine the speed of movement
public Touch touch; //Using this variable, we will determine if there was at least some touch on the screen
void Start() {
speedModifier = 2.01f;
}
public void Update() {
}
public void Movement() { //Creating a "Movement" method to call it in the "SelectObject" script
touch = Input.GetTouch(0);
if(touch.phase == TouchPhase.Moved) {
transform.position = new Vector3(transform.position.x + touch.deltaPosition.x * speedModifier, transform.position.y, transform.position.z + touch.deltaPosition.y * speedModifier);
}
}
}
But when I start the game, the cylinder still doesn't move.
What am I doing wrong?
Not 100% clear on what you're trying to do but have you tried passing your location into the Movement() method? Something like this.
public void Movement(Vector3 targetLocation) {
transform.position = targetLocation;
}
Then you'd call it like this.
Movement(Input.touches[0].position);
Just a note since I noticed your speed modifier. The way your code is currently set up is going to instanly move the object to the touch location. If you would like to have it smoothly move to it at a specified speed you'll need to look up Lerping or store the previous position, current, and target position.
I am having a problem with Raycasting. All I want to do is always know the position of my cursor in world space and it works, but only if the cursor is moving. when the cursor is not moving it jumps to a random point around 4 units down on the x and z-axis.
public class CameraMovementRay : MonoBehaviour
{
public Camera playerCam;
Ray cursorRay;
Vector3 playerPos;
public RaycastHit cursorHit;
public LayerMask clickPlain;
public bool cursorHittingFloor;
// Update is called once per frame
void Update()
{
cursorRay = playerCam.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(cursorRay, out cursorHit, 100f, clickPlain))
{
print(cursorHit.point);
Debug.DrawLine(cursorRay.origin, cursorHit.point, Color.red);
cursorHittingFloor = true;
}
else
{
Debug.LogError("Not on the grund");
cursorHittingFloor = false;
}
}
That wasn't working out but I did find code that does
``
public class LookAtMouse : MonoBehaviour
{
public Camera playerCamera;
Plane movementPlane = new Plane(Vector3.up, 0f);
Vector3 lookPoint;
Ray CursorRay;
// Update is called once per frame
void Update()
{
CursorRay = playerCamera.ScreenPointToRay(Input.mousePosition);
float enter = 0.0f;
movementPlane.Raycast(CursorRay, out enter);
lookPoint = CursorRay.GetPoint(enter);
print(lookPoint);
Debug.DrawLine(CursorRay.origin, lookPoint);
transform.LookAt(lookPoint);
}
}
``
Have you tried using Camera.ScreenToWorldPoint instead of Camera.ScreenPointToRay? I think it might work better for your purpose because it takes a Vector2 (MousePosition) in pixels and converts it conveniently to World Space Point. The Unity documentation to what I'm referring to is: https://docs.unity3d.com/ScriptReference/Camera.ScreenToWorldPoint.html
Let me know how it works out
I want to move my player around in my level without a NavMesh Agent.
I was thinking something about raycasting, but i have tried everything and even looked up videos and searched on google about it, can't seem to find anything that works
Plz help!
you can use this for moving to mouseclick position.
This method will move object or player to the position where mouse is clicked on screen.
sorry for syntax error i have typed directly here
using UnityEngine;
using System.Collections;
public class MouseMovement : MonoBehaviour
{
public float speed = 10f;
bool isplayermove = false;
// Use this for initialization
private void Start ()
{
Vector3 playerpos = transform.position;
}
// Update is called once per frame
private void Update ()
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
is moveplayer = true;
}
if(ismoveplayer)
{
Vector3 mousePos = Camera.main.ScreenToWorldPoint(new Vector3(input.mousepos.x,input.mousepos.y,input.mousepos.z);
transform.position = Vector3.MoveTowards(transform.position,new Vector3(mousepos.x,transform.position.y,mousepos.z),speed * time.deltatime);
if(transform.position == mousepos)
{
ismoveplayer = false;
}
}
}
}
The camera that the script is attached to is above high the terrain look on the terrain from the top. And now when i click the mouse i'm getting List points. But now i want to make that when i click the mouse it will give me the position on the terrain including terrain high places like hills.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GetMousePosition : MonoBehaviour
{
private bool isMousePressed;
private List<Vector3> pointsList;
private Vector3 mousePos;
// Use this for initialization
void Start()
{
isMousePressed = false;
pointsList = new List<Vector3>();
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
isMousePressed = true;
pointsList.RemoveRange(0, pointsList.Count);
}
else if (Input.GetMouseButtonUp(0))
{
isMousePressed = false;
}
if (isMousePressed)
{
mousePos = GetComponent<Camera>().ScreenToWorldPoint(Input.mousePosition);
mousePos.z = 0;
if (!pointsList.Contains(mousePos))
{
pointsList.Add(mousePos);
}
}
}
}
You would do this with a Raycast, you can cast a ray from the camera position to the terrain and then get all of the details you desire using the data that you get back.
So in your case if you wanted to add the hit point to the list you would do something like this
float distance = 100f;
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
isMousePressed = true;
pointsList.RemoveRange(0, pointsList.Count);
}
else if (Input.GetMouseButtonUp(0))
{
isMousePressed = false;
}
if (isMousePressed)
{
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (ray, out hit, distance))
{
if(!pointsList.Contains(hit.point)
{
pointsList.Add(hit.point);
}
}
}
}
It should be noted in the above example that Physics.Raycast has many overloads which allow you to customise how the ray fires. You can also use the hit and ray variables to get much more information such as the specific collider it hit as well as the world position at which the ray originated from, more information on how to do just that can be found in the Unity API documentation page for the Physics Raycast.
If you'd like to learn more about Raycasting I'd recommend watching the official Unity video on the topic which goes into further detail, you'll be using it a lot in game development so it's worth learning as much as you can about it before moving forward.
This is my click to move code, This is my first question, so I'm new to this. If you need any more information I will be happy to give it to you!
I have made a top-down dungeon game (Like Diablo), I completed creating all of the dungeon levels and started to animate and move my player, I got it working starting on the third and last level and it works perfect, I was happy as this is my first time making a game. I created a prefab of the character and moved it into the other levels and only got error when I clicked to move, I have tried to add them in separately but still didn't work sadly.
using UnityEngine;
using System.Collections;
public class ClickToMove : MonoBehaviour
{
public float speed;
public CharacterController controller;
private Vector3 position;
public AnimationClip idle;
public AnimationClip run;
public static Vector3 cursorPosition;
// Use this for initialization
void Start ()
{
position = transform.position;
}
// Update is called once per frame
void Update ()
{
if(Input.GetMouseButton(0))
{
//Locate where the player clicked on the terrain
locatePosition();
}
//Move the player to the position
moveToPosition();
}
void locatePosition()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, 1000))
{
if(hit.collider.tag!="Player"&&hit.collider.tag!="Enemy")
{
position = hit.point;
}
}
}
void locateCursor()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, 1000))
{
cursorPosition = hit.point;
}
}
void moveToPosition()
{
//Game Object is moving
if(Vector3.Distance(transform.position, position)>1)
{
Quaternion newRotation = Quaternion.LookRotation(position- transform.position, Vector3.forward);
newRotation.x = 0f;
newRotation.z = 0f;
transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, Time.deltaTime * 10);
controller.SimpleMove(transform.forward * speed);
GetComponent<Animation>().CrossFade("run");
}
//Game Object is not moving
else
{
GetComponent<Animation>().CrossFade("idle");
}
}
}
As Catwood said, double clicking on the error in the console will take you to the relevant line of code that's causing the exception. I'd expect it to be one of the GetComponent calls though as you're trying to call the CrossFade function on something that might return null (in the case that the Animator component can't be found).
As a side note, you should avoid using GetComponent like this as it's inefficient. Instead, create a private / protected variable and store the reference when you first get the component.