Raycast only returns false, even when true expected - unity3d

I have the following FollowingNPC game object, which is supposed to follow the Player object if there is direct vision:
Here the Player object:
The BlockingLayer and Player Layers have the physics collision enabled between each other:
The FollowingNPC hast the following script attached, that always returns a "Not Hit" result: Raycast always false. This is not the expected output, as both objects seem to have a clear view between each other and the debug ray can be drawn without problems.
public class FollowingNPC : MonoBehaviour
{
private Vector3 heading, direction;
private float distance;
void Update()
{
heading = GameObject.FindGameObjectWithTag("Player").transform.position - transform.position;
distance = heading.magnitude;
direction = heading / distance;
RaycastHit hit;
if (Physics.Raycast(transform.position, direction, out hit))
{
if (hit.transform== GameObject.FindGameObjectWithTag("Player").transform)
{
Debug.DrawRay(transform.position, direction * distance, Color.red);
Debug.Log("Hit Player");
}
else
{
Debug.DrawRay(transform.position, direction * distance, Color.yellow);
Debug.Log("Hit Wall");
}
}
else
{
Debug.DrawRay(transform.position, direction * distance, Color.white);
Debug.Log("Not Hit");
}
}
}
Solved:
As derHugo suggested, Physics2D.Raycast should be used here. This function does not return a bool, so this is the implementation that worked for me:
void Update()
{
heading = GameObject.FindGameObjectWithTag("Player").transform.position - transform.position;
RaycastHit2D hit = Physics2D.Raycast(transform.position, heading.normalized, LayerMask.GetMask("Player"));
if (hit.collider != null)
if (hit.transform == GameObject.FindGameObjectWithTag("Player").transform)
Debug.Log("Hit Player");
else
Debug.Log("Hit Wall");
else
Debug.Log("Not Hit");
}
Also, it's important to note that, even with the mask, the Raycast returned the hit with the collider of FolloginNPC, so I had to disable it. I'll have to do some investigation or search a workaround.

Note that in Unity the Physics and Physics2D are completely independent and separated Physics engines!
Built-in 3D physics (Nvidia PhysX engine integration)
Built-in 2D physics (Box2D engine integration)
You have Rigidbody2D and Collider2D so you would rather want to use Physics2D.Raycast!
You should also strongly avoid using FindGameObjectWithTag in Update and even worse multiple times as it is quite expensive! Rather do it once and store the result.
// If possible and best would be to already reference it via the Inspector
[SerilaizeField] private Transform player;
// As fallback get it ONCE on runtime
private void Awake()
{
if(!player) player = GameObject.FindGameObjectWithTag("Player").transform;
}
void Update()
{
// actually those wouldn't really need to be fields
heading = player.position - transform.position;
distance = heading.magnitude;
// This line isn't really necessary
// If something I would use
//direction = heading.normalized
direction = heading / distance;
var hit = Physics2D.Raycast(transform.position, direction);
if (hit.collider)
{
if (hit.transform == player)
{
Debug.DrawRay(transform.position, direction * distance, Color.red);
Debug.Log("Hit Player");
}
else
{
Debug.DrawRay(transform.position, direction * distance, Color.yellow);
Debug.Log("Hit Wall");
}
}
else
{
Debug.DrawRay(transform.position, direction * distance, Color.white);
Debug.Log("Not Hit");
}
}
Later you should also remove all these Debug.Log since they are also quite expensive when done in Update!

Related

Unity Boxcast 3D always return false

I'm learning Unity and want to use Boxcasting to detected if the player is grounded. I have this code:
void Jump()
{
float maxDistance = 0.1f;
RaycastHit hit;
bool isGrounded = Physics.BoxCast(transform.position, transform.lossyScale / 2, Vector3.down, out hit, transform.rotation, maxDistance, groundMask);
if (isGrounded)
rb.AddForce(Vector3.up * jumpForce);
Debug.Log(isGrounded);
}
But it always return false. If I have it inside a OnDrawGizoms method, it works as indented, but if I have it in my Jump() method (as the code above) will it always return false.
I would appreciate any help I could get.

How to make collision work with translate UNITY

I can't use rigidbody method to move player so i need to move it with Transform.translate
I know collision work only with rigidbody but i don't want make it like that
you could cast a ray to detect collisions. this is just a simple script where collision is detected in the forward direction of the transform one frame before it happens (with a simple cube of size 1 unit).
public float speed;
bool collision;
void Update()
{
Ray ray = new Ray(transform.position, transform.forward);
if (Physics.Raycast(ray, 0.5f + speed * Time.deltaTime))
{
collision = true;
}
else collision = false;
if (!collision)
{
transform.Translate(transform.forward * speed * Time.deltaTime);
}
}

Unity 2D - Tap Image to accelerate car

I am making a Hill Climb Racing clone as a school project. Currently my car is accelerating with the A and D keys in my editor (movement = Input.GetAxis("Horizontal");), however the game has to be for Android, therefore like in the OG game, I added 2 sprites for brakes and pedals and added EventSystems to them eg.:
public void OnPointerDown(PointerEventData eventData)
{
gas.sprite = OnSprite_gas;
is_clicking = true;
}
and I dont know how to change acceleration to when the gas image is clicked and held down and how to brake (but not go backwards) when the brake is held down.
You seem to be on the right track.
In the car's Update() method, you will want to check if the brake or accelerator button is_clicking property is set, and handle the movement force.
This could look something like:
void Update()
{
if (accelerator.is_clicking)
{
movement = new Vector3(1f, 0f, 0f) * speed;
}
else if (brake.is_clicking)
{
movement = new Vector3(-1f, 0f, 0f) * speed;
}
else
{
movement = new Vector3(0f, 0f, 0f);
}
}
void FixedUpdate()
{
rb.AddForce(movement * Time.fixedDeltaTime);
}
You could then check if the velocity is close to 0 to stop applying the brake force.

Dragging an object with raycast is laggy

When dragging an object slowly with a raycast the object moves with a bit of lag.
When dragging the object fast the mouse pointer gets out of the field of layer raycasting so the object is no more moving.
The main project is dragging a cube on a plane.
But in order to make the project more simpler, I opened a new 2D project and made a circle and assigned to it the following script, and attached to it a sphere collider (the main target is in 3D space).
// If some one wrote:
private Vector2 deltaPos;
void Update () {
Vector2 touchPos;
if (Input.GetMouseButtonDown (0)) { // Clicking the Target
RaycastHit hit;
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray, out hit, Mathf.Infinity)) {
touchPos = new Vector3 (hit.point.x, hit.point.y);
deltaPos.x = touchPos.x - transform.position.x;
deltaPos.y = touchPos.y - transform.position.y;
Debug.Log ("You Clicked Me");
}
}
if (Input.GetMouseButton (0)) {
RaycastHit hit;
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray, out hit, Mathf.Infinity)) {
transform.position = new Vector2 (hit.point.x - deltaPos.x, hit.point.y - deltaPos.y);
}
}
}
I expected to drag the sphere regularly, but what happens is that the pointer goes outside the sphere collider when moving fast, therefore the circle stops moving.
I found this article, then I changed the void from Update() to FixedUpdate() but same result.
Try putting your physics code in FixedUpdate() function which is built for physics calculation. then if it's laggy, you can changeFixed Timestep in physics settings.
Fixed Timestep: A framerate-independent interval that dictates when physics calculations and FixedUpdate() events are performed.
https://docs.unity3d.com/Manual/class-TimeManager.html
EDIT
this code:
if (Physics.Raycast (ray, out hit, Mathf.Infinity))
checks if the raycast has hit something, therefore when the pointer goes out of the sphere there is nothing else to hit, so the if condition returns false and you cannot move it, to solve the problem add a big quad or plane as child to your camera and make sure it fills the camera view perfectly, and it's behind all your other scene elements.
you also can make a script that sets this plane for you.
EDIT 2
As another approach to solve the issue, you can use flags.
Add this to your camera, or edit it to your needs.
public class DragObjects : MonoBehaviour
{
Camera thisCamera;
private Transform DraggingObject;
bool DraggingFlag = false;
RaycastHit raycast;
Ray ray;
Vector3 deltaPosition;
void Start()
{
thisCamera = GetComponent<Camera>();
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
ray = thisCamera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out raycast, Mathf.Infinity))
{
DraggingObject = raycast.collider.transform;
DraggingFlag = true;
deltaPosition = thisCamera.ScreenToWorldPoint (Input.mousePosition) - DraggingObject.position;
}
}
else if (Input.GetMouseButton(0))
{
if (DraggingFlag)
{
DraggingObject.position = new Vector3 (thisCamera.ScreenToWorldPoint (Input.mousePosition).x - deltaPosition.x, thisCamera.ScreenToWorldPoint (Input.mousePosition).y - deltaPosition.y, DraggingObject.position.z);
}
}
else if (Input.GetMouseButtonUp(0))
{
DraggingFlag = false;
}
}
}
Remember to cash your Camera.main in a variable at the start, because it is not performant and does this in the background:
GameObject.FindGameObjectsWithTag("MainCamera").GetComponent<Camera>();

Player touch input and continuous one direction movement combination

I want to create Mmm Finger 2 game like player movement, here is game play video: Mmm Fingers 2 by Noodlecake Android Gameplay ᴴᴰ
In this player is continuously moving upward as well based on touch, you have full control over player movement. These both things together not working properly for me. Finger based movement also working in all directions still you are continuously moving up.
I have tried to write some code with different ways but can't able to create smooth experience in game play.
Upto now I reached up to here:
void Update ()
{
// checking condition for death
if (!isAlive)
return;
#if UNITY_EDITOR
// executed in Unity editor
if (Input.GetMouseButtonDown (0)) {
//Get the mouse position on the screen and send a raycast into the game world from that position.
Vector2 worldPoint = Camera.main.ScreenToWorldPoint (Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast (worldPoint, Vector2.zero);
//If something was hit, the RaycastHit2D.collider will not be null.
if (hit.collider != null && hit.transform.CompareTag (GameConstants.TAG_HUMAN_PLAYER)) {
playerFound = true;
GameManager.Instance.IsGameRunning = true;
GameHUDController.Instance.HideGameInstruction();
hidePlayerName();
}
} else if (Input.GetMouseButtonUp (0)) {
playerFound = false;
StartCoroutine (PerformGameOver ());
}
Vector3 nextPosition = transform.position;
nextPosition.x += (Time.deltaTime * speed * 0.5f);
transform.position = nextPosition;
if (playerFound) {
Vector3 worldPoint = Camera.main.ScreenToWorldPoint (Input.mousePosition);
// worldPoint.x += (speed * Time.deltaTime);
worldPoint.z = 0f;
transform.position = worldPoint;
// transform.position = Vector3.Lerp (transform.position, worldPoint, Time.deltaTime * 10f);
}
}
Please give some help into this.