Im making a system where you can press a certain key and it will place down an object at your mouse location. Every time you press the key '1' it should place it down at the mouse location but for some reason every frame the Input.GetKeyDown("Alpha1"); is registered as true so wherever i move my mouse it places the block down no matter what I press. This has been happening to me alot recently and I cant seem to find any answers.
using UnityEngine;
public class CubePlacer : MonoBehaviour
{
private Grid grid;
public KeyCode place;
private void Awake()
{
grid = FindObjectOfType<Grid>();
}
private void Update()
{
if (Input.GetKeyDown(place)) ;
{
RaycastHit hitInfo;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hitInfo))
{
PlaceCubeNear(hitInfo.point);
}
}
}
private void PlaceCubeNear(Vector3 clickPoint)
{
var finalPosition = grid.GetNearestPointOnGrid(clickPoint);
GameObject.CreatePrimitive(PrimitiveType.Cube).transform.position = finalPosition;
//GameObject.CreatePrimitive(PrimitiveType.Sphere).transform.position = nearPoint;
}
}
if (Input.GetKeyDown(place)) ; // <--- remove this semi colon
{
RaycastHit hitInfo;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hitInfo))
{
PlaceCubeNear(hitInfo.point);
}
}
You need to remove the semicolon after the If statement. It terminates the line and causes the block afterwards to execute every time the Update() method is called.
Related
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);
}
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.
I have the following code, but i'm having some problems. Every time update is called, the character move to the point i give him to. But i just give him a point when i click with the mouse on the ground, the problem starts when i try to make it animate the character.
If i pass the value of the animation on the clickToMove() method it'll always play that animation even if we aren't moving. And if i place clickToMove inside the "if clicked" the character will teleport and not move towards. I can't think in a way to do the animation properly, only when the object is moving, and goes back to idle when it's stopped, even if the clickToMove() is playing all the time.
using UnityEngine;
using System.Collections;
public class ClickScript : MonoBehaviour
{
public float moveSpeed;
public float minDistance;
Vector3 mouseClick; //Creates a variable to save the constant of the hit from raycast
private Animator anim;
private Rigidbody rigidB;
// Use this for initialization
void Start()
{
anim = GetComponent<Animator>();
rigidB = GetComponent<Rigidbody>();
}
// Update is called once per frame
void FixedUpdate()
{
if (Input.GetMouseButtonDown(1))//If clicked
{
clickPosition(); //Gets the click position
}
if (Vector3.Distance(transform.position, mouseClick) > minDistance) //If the click distance is bigger than the minimal
{
//It is allways moving, but since there's no click position it doesn't move when not clicked
clickToMove();
}
}
void clickPosition()//This function throw a raycast on the ground and save the position on mouseClick to make the char move to there
{
RaycastHit clickHit; //creates a constant with the infos from the raycast
Ray mouseClickPosition = Camera.main.ScreenPointToRay(Input.mousePosition); //creates a constant to save the mouse position
if (Physics.Raycast(mouseClickPosition, out clickHit, 100.00f))//throw a raycast returning the mouse position and more infos
{
Debug.Log("Click at " + clickHit.point); //Show where were clicked
mouseClick = clickHit.point;//mouseClick receive the position of the click
}
}
void clickToMove() //this function make the player look at the click and move to mouseClick
{
mouseClick.y = transform.position.y; //get rid of the y to fix rotation bugs
transform.LookAt(mouseClick);//look at the poit you clicked
transform.position = Vector3.MoveTowards(transform.position, mouseClick, moveSpeed * Time.deltaTime);//move to the clickpoint
}
}
How about this way?
bool _isAnimating = false;
// Update is called once per frame
void FixedUpdate()
{
if (Input.GetMouseButtonDown(1))//If clicked
{
clickPosition(); //Gets the click position
//start animation here!!!
//animator.SetBool("bWalk", false);
//and set animation state to true
_isAnimating = true;
}
if (Vector3.Distance(transform.position, mouseClick) > minDistance)
{
clickToMove();
}
else if(_isAnimating)
{
//turn off the animation here!!!
//animator.SetBool("bStop", false);
//and set to false
_isAnimating = false;
}
}
Please keep in mind that I'm new to unity. I created an 2D android game app.
I created a start button( from an image) and attacted a Box colider, and a C# script to it.
When I click the "button" I want the program to move to the next "Level", that Works except that I want it to only Work if i click the object and not everywhere on the game.
This is the C#:
using UnityEngine;
using System.Collections;
public class StartGame : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown(0)) {
Application.LoadLevel("Game");
}
}
}
I searched alot about this and maybe people say that to solve this you have to use, Ray and RaycastHit But I cant get that to Work either.
Here is what I tried to with Ray & RaycastHit
// Update is called once per frame
void Update () {
if ((Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) || (Input.GetMouseButtonDown(0)))
{
RaycastHit hit;
Ray ray;
#if UNITY_EDITOR
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
#elif (UNITY_ANDROID || UNITY_IPHONE || UNITY_WP8)
ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
#endif
if(Physics.Raycast(ray, out hit))
{
Application.LoadLevel("Game");
}
}
}
Any help would be so appriciated.
Probably the easiest way is to add box collider and script component including function below to the gameobject.
void OnMouseOver()
{
if (Input.GetMouseButtonDown(0))
{
Application.LoadLevel("Game");
}
}
Edit:
I'm guessing that the original code is not working on your scene, because you are using box collider 2d. Physics.Raycast is testing against 3D colliders. When I run it with the 3D version box collider it works fine.