so I'm trying to add a script to an enemy AI to detect the player as long as the player isn't obstruted by anything. I'm using a Raycast to achive this but my script isn't working at all. What am I doing wrong?
public Transform playerPos;
bool canSee = false;
private void Update()
{
RaycastHit hit;
var playerTarget = (transform.position - playerPos.position).normalized;
if (Physics.Raycast(transform.position, playerTarget, out hit))
{
canSee = true;
Debug.Log("HIT");
}
else
Debug.Log("NO HIT");
canSee = false;
}
When I hit play in unity Debug.Log reads "HIT" regardless if I'm obscured by a wall or not. Sorry guys, I'm an absolute beginner here so any help is appreciated.
Related
So I'm working on a little top-down perspective game and wanted to add a combat system. I set it up so that it'll shoot a raycast and if it hits an enemy they'll take damage but the raycast is returning nothing.
Vector3 mouse_pos = Input.mousePosition;
mouse_pos.z = 5.23f;
Vector3 objectPos = Camera.main.WorldToScreenPoint(transform.position);
mouse_pos.x = mouse_pos.x - objectPos.x
mouse_pos.y = mouse_pos.y - objectPos.y
if (Input.GetMouseButtonDown(0))
{
Raycast hit;
print(Physics.Raycast(transform.position, mouse_pos, out hit));
if (Physics.Raycast(transform.position, mouse_pos, out hit))
{
if (hit.collider.gameObject.name.Contains("enemy"))
{
hit.collider.gameObject.GetComponent<enemyMovement>().life -= 1;
}
}
}
The print returns false even when there's a gameobject there. It's probably a simple problem but I don't know what to do lol.
I changed the code for you, because I am not very familiar with the ray, thank you and hope it can help you.
void update(){
if (Input.GetMouseButtonDown(0))
{
// When the left mouse button is pressed, emit a ray to the screen
position where the mouse is located
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
if (Physics.Raycast(ray,out hitInfo))
{
// When the ray collides with the object, draw the ray in the scene view
Debug.DrawLine(ray.origin, hitInfo.point, Color.red);
if (hitInfo.collider.gameObject.name.Contains("enemy"))
{
hitInfo.collider.gameObject.GetComponent<enemyMovement>().life -= 1;
}
}
}
}
I'm making a small space game in 3D, but it looks awful when my ship is rotating in the middle of movement
So can someone please help me with code ? I need to rotate to that position and than move to it. (And i forgot to say, that rotation needs to be on Y axis)
Here is my code for that movement.
NavMeshAgent agent;
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
void Update()
{
if(Input.GetMouseButton(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit) && hit.collider.tag == "Ground")
{
agent.SetDestination(hit.point);
}
}
}
You are supposed to stop the agents rotation.
this is the code:
NavMeshAgent agent;
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
void Update()
{
if(Input.GetMouseButton(0))
{
agent.updateRotation = false;
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit) && hit.collider.tag == "Ground")
{
agent.SetDestination(hit.point);
}
}
}
And I also have a more efficient way for you to check if the player is on Ground.
Here is what you should do instead of
hit.collider.tag == "Ground
First, make a Layer named "Ground" (anything... depends on you).
Then, add a LayerMask in the script above the NavMeshAgent. public LayerMask groundLayer
And in the if statement
do this:
if (Physics.Raycast(ray, out hit, groundLayer))
{
agent.SetDestination(hit.point);
}
What this does is, it only considers the click on objects with the selected layer.The plus point here is that you can select multiple layers in the Inspector.
And do not forget to select the layer in the Inspector.
Thank you! <3
I make a navmesh controller and my player move to the touched or clicked place but I want the player to play a walking anime when is moving but when it reaches the destination and not moving play idle animation.
Please explain in C#.
I made script it play walking but it doesn't play idle when player reaches its destination
public class navmesh : MonoBehaviour
{
UnityEngine.AI.NavMeshAgent agent;
public Animator anim;
public Transform player;
public GameObject obj;
void Start()
{
agent = GetComponent<UnityEngine.AI.NavMeshAgent>();
anim = GetComponent<Animator>();
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Vector3 mouse = Input.mousePosition;
Ray castPoint = Camera.main.ScreenPointToRay(mouse);
RaycastHit hit;
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 100))
{
agent.destination = hit.point;
anim.SetBool("walk", true);
obj.transform.position = hit.point;
}
else
{
anim.SetBool("walk", false);
}
}
}
}
You can use the "NavMeshAgent.remainingDistance" property to check if it is within a small range. Here is the doc on navmeshagent for more
(example)
if(agent.remainingDistance > 0.1f) {
// Play anims
}
I would recommend not hard-coding that less-than value as it can be nicer to adjust it in the inspector.
I'm still learning Unity and right now I'm trying to make my player able to jump. Of course I don't want my player to be able to jump on forever, so my idea was to only enable jumping when the player is in contact with a floor object. This is the code I have so far:
public class PlayerController : NetworkBehaviour
{
public float speed; // Player movement speed
private bool grounded = true; // Contact with floor
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Show a different color for local player to recognise its character
public override void OnStartLocalPlayer()
{
GetComponent<MeshRenderer>().material.color = Color.red;
}
// Detect collision with floor
void OnCollisionEnter(Collision hit)
{
if (hit.gameObject.tag == "Ground")
{
grounded = true;
}
}
// Detect collision exit with floor
void OnCollisionExit(Collision hit)
{
if (hit.gameObject.tag == "Ground")
{
grounded = false;
}
}
void FixedUpdate()
{
// Make sure only local player can control the character
if (!isLocalPlayer)
return;
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
rb.AddForce(movement * speed);
// Detect space key press and allow jump if collision with ground is true
if (Input.GetKey("space") && grounded == true)
{
rb.AddForce(new Vector3(0, 1.0f, 0), ForceMode.Impulse);
}
}
}
But it seems OnCollisionEnter and OnCollisionExit never trigger. So the player is still able to jump whenever he wants. Am I doing something wrong?
Edit: It seems OnCollisionEnter and OnCollisionExit are triggered perfectly fine. It's just the if statements returning false. I have no idea why though.
if (GameObject.Find("Ground") != null) returned true.
Edit 2: Strangely enough both of these return Untagged:
Debug.Log(hit.gameObject.tag);
Debug.Log(hit.collider.tag);
Please give us more information
Please tell me which version of unity you are using?
Have you updated the project to some other latest version of unity?
Also give a screen shot of your 'tag' array.
I have walls that block player movement in the scene. I want to drag the player when the path is free and disable when the player hits the wall. I can enable and disable with mouseButtonDown(). This enable only when the mouse is pressed. I dont want this.
if (Input.GetMouseButtonDown(0))
{
if (enableDrag ==false)
enableDrag = true;
}
OnMouseDrag()
{
if(enableDrag== true)
{
....
}
}
.....
void OnCollisionEnter2D (Collision2D coll)
{
if (coll.gameObject.tag == "Walls")
{
enableDrag= false;
}
}
Also I dont need unstable motion of the player when it collides with the wall.
Any comment from your experience is heplful.
Why don't you change the logic up. It sounds like you want a constant drag unless colliding with a wall. So you could in that case say:
Pseudo:
Inside your Update()
If (not colliding with walls)
DragObject()
This would require you to know when you are no longer colliding. Perhaps using OnCollisionExit.
Eventhough it is too late to answer, here is how I solved the problem.With this approach you can drag the player continously as far it is not colliding with obstacles.
void OnMouseOver ()
{
Vector2 mousePos;
Vector3 mousePosWorld = Camera.main.ScreenToWorldPoint (Input.mousePosition);
mousePos.x = mousePosWorld.x;
mousePos.y = mousePosWorld.y;
this.transform.position = Vector3.MoveTowards (transform.position, new Vector3 (mousePosWorld.x, mousePosWorld.y, 0), speed * Time.deltaTime);
if (enableDrag) {
Vector3 cursorPoint = new Vector3 (Input.mousePosition.x, Input.mousePosition.y, 0);
Vector3 cursorPosition = Camera.main.ScreenToWorldPoint (cursorPoint) + offset;
transform.position = new Vector3 (cursorPosition.x, cursorPosition.y, 0);
}
If void OnCollisionEnter2D (Collision2D coll)
{
if (coll.gameObject.tag == "Obstacle")
{
enableDrag= false;
}
}