So I'm working on a door opening system where I check trough a Raycast if the user has the middle of the screen focust on the doorknop. Here is the bit of my code that isn't working:
private void Update()
{
if (Physics.Raycast(Camera.transform.position, Camera.transform.forward, out rayHit, Distance))
{
Debug.DrawRay(Camera.transform.position, Camera.transform.forward, Color.blue);
Collider col = rayHit.collider;
if (col.tag == DoorKnopTag)
{
DoorIndicator.SetActive(true);
}
else
{
DoorIndicator.SetActive(false);
}
}
else
DoorIndicator.SetActive(false);
}
So I didn't put the code in that checks if the mouse is clicked when the player selects the doorknob but I'm sure that isn't the problem.
The problem is that when I check the Ray in my scene the line is flickering very hard. I debugged a bit and came the conclusion that the Camera.transform.forward is constantly changing even if I don't change the Camera.tranform.position. When I changed the direction of the Physics.Raycast to a constant Vector3 it didn't flicker anymore so I think that the problem is in the transform.forward. But I can't see how to fix it.
Try using FixedUpdate() instead of Update().
For physics events you should use FixedUpdate(),
For graphical events you should use Update().
The reason of raycast flickering is caused by casting raycast from a collider most of the time. Check whether you have a collider on raycast origin point or not.
Related
I have the following setup:
A ball object that has a CircleCollider 2d with a frictionless, full-bounce (1) material. The collider is not a trigger. It also has a rigidbody2d on it, with no gravity, some mass, Continuous collision detection and Interpolate set to Interpolate. It also has a script with this code:
Rigidbody2D rb;
private void Awake() {
rb = GetComponent<Rigidbody2D>();
}
Vector2 lastVelocity;
private void FixedUpdate() {
lastVelocity = rb.velocity;
}
private void OnCollisionEnter2D(Collision2D other) {
if (other.gameObject.tag == "Block" && isPiercing) {
rb.velocity = lastVelocity;
}
}
A few Block objects that have a Box Collider 2d on them (also not set to be triggers), nothing else.
The idea is, if I have the isPiercing property set on the ball, it should pass through. Otherwise, it should use default behaviour and the ball should bounce off the blocks as normal (which it does fine).
What actually happens is, there's some 'jitter'; as soon as the ball hits the block, it looks like it back-tracks on its path slightly. It still passes through; just it looks like it hit a speed bump along the way.
Do I need to move the ball forwards along its path when it enters the collision to make up for the bounce it's about to do (or is in the process of doing)?
Maybe get a clip of what's going wrong, but from what I can see, when the ball hits a block with piercing, then you're setting its velocity to its FixedUpdate() velocity. I don't know why you're doing this, but FixedUpdate() is calculated before unity does its physics calculations. I'm not sure, but it seems as if this may move the ball back slightly, like you are saying.
My suggestion would be to not set its current velocity to its FixedUpdate velocity.
Hope this works!
I am building a 3d topdown shooter. The player controls the avatar with the keyboard and the reticule with the mouse.
I found a simple way to implement the reticule based on this article:
https://gamedevbeginner.com/how-to-convert-the-mouse-position-to-world-space-in-unity-2d-3d/
I defined an object which represents the reticule and attached this script:
public class Reticule : MonoBehaviour
{
Camera mainCamera;
Plane plane;
float distance;
Ray ray;
// Start is called before the first frame update
void Start()
{
mainCamera = Camera.main;
plane = new Plane(Vector3.up, 0);
// This would be turned off in the game. I set to on here, to allow me to see the cursor
Cursor.visible = true;
}
// Update is called once per frame
void Update()
{
ray = mainCamera.ScreenPointToRay(Input.mousePosition);
if (plane.Raycast(ray, out distance))
{
transform.position = ray.GetPoint(distance);
}
}
}
This works, but the issue is that the reticule is lagging behind the mouse cursor, and catches up when I stop moving the mouse.
Is this because this method is just slow. Is there another simple way to achieve the same result?
the issue is that the reticule is lagging behind the mouse cursor, and catches up when I stop moving the mouse
That's normal, your mouse cursor is drawn by the graphics driver (with the help of WDM) as fast as the mouse data information comes over the wire, while your game only renders at a fixed framerate (or slower). Your hardware mouse will always be ahead of where your game draws it or anything related to it.
Some things that can help with working around this:
Don't show the system cursor, instead show your own. That way the cursor you show will always be in the same place your game thinks it is (since it drew it) and you won't have this issue. Careful with this however, because if your game's frame rate starts dipping it will be VERY noticeable when your cursor movement isn't smooth anymore.
Don't tie objects to your cursor. The issue doesn't show with normal interactions, like clicking buttons. You will notice this in RTS games when drawing boxes around units, but I struggle to think of another example of this.
Like above, but less restrictive, you could lerp the objects tied to your cursor in place, so they're always and intentionally behind it. It makes it look more gamey, which isn't that bad for a, you know, game. Though I wouldn't do this for a twitchy shooter, of course.
I've been tearing my hair out for weeks just trying to detect a collision between a RigidBody and a BoxCollider tied to a spot light that is tied to the camera, I want to detect when the player is flashing their flashlight at something, but for some reason this doesn't work.
I don't think it's detecting the collision at all, the variable "test" does not change and nothing appears in console, the flashlight hitbox I'm sure is large enough, but the console still gives no indication of anything happening, I was following this tutorial: https://www.youtube.com/watch?v=QRp4V1JTZnM
and here's the simple code I made:
void OnCollisionEnter(Collision col) {
if (col.gameObject.name == "Spot_Light") {
Debug.Log("detected");
test = 375;
}
}
If you marked trigger in your collider, you cannot use the OnCollisonEnter to detect a collison, you should use the OnTriggerEnter instead.
I have my Unity 2D project set up so that the bullet is a trigger and will detect and collisions but not interact with the environment, and my enemy being a collider so that it will do both. I don't know if the fact that they are two different types affects collisions, but I thought I'd include that detail incase it did. I know this issue is not caused by my bullet moving too quickly since when I turn the speed of the bullet down the issue persists. I will include the code for the enemy collision and the bullet collision detection here:
void OnCollisionEnter2D (Collision2D coll)
{
if (coll.gameObject.tag == "Proj") {
Destroy(gameObject);
Debug.Log("Hit");
}
Now for the bullet:
void OnTriggerEnter2D(Collider2D hitInfo)
{
if (hitInfo.gameObject.tag == "Enemy") {
Destroy(gameObject);
}
The bullet is detecting a collision with an enemy and deleting itself, but the enemy is not detecting a collision with the bullet and taking damage/deleting itself. Even when I turn off the Destroy(gameObject) part of the bullet code so that it doesn't destroy itself on collision I still have the same problem so I know it isn't matter of it deleting before anything detects. I hope I was thorough enough with my explanation and that someone can help me resolve this issue.
Image of the inspectors: https://imgur.com/a/TLfcNcp
The bullet needs to be a non-trigger collider as you are calling OnCollisionEnter and not OnTriggerEnter from the enemy script.
Please show the settings of each collider, also OnCollisionEnter2D and OnTriggerEnter2D are 2 different things, and will occur in different conditions, so make sure that you are using the right one for the player.
I'm not entirely familiar with trigger behaviour, as it's been a while since I've played around with those, but this bit of documentation for MonoBehaviour.OnTriggerEnter2D(Collider2D) is an important starting point for solving your problem:
Trigger events are only sent if one of the Colliders also has a Rigidbody2D attached.
I can't say for sure, but your screenshots suggest that there is no Rigidbody2D involved.
Interestingly,
documentation for Collider2D.OnTriggerEnter2D(Collider2D) neglects to specify that a Rigidbody2D is necessary. I'm not sure what this implies; both MonoBehaviour.OnTriggerEnter(Collider) and Collider.OnTriggerEnter(Collider) (the 3D analogues) are said to require a RigidBody. Both of these pages also claim
If both GameObjects have Collider.isTrigger enabled, no collision happens.
However, the example code from Monobehaviour.OnTriggerEnter2D(Collider2D) claims that setting both 2D colliders as triggers will still allow the function to be called.
I am trying to learn unity, and made my first own game and stucked at the beginning. The first idea was to drop a box (cube) to the mouse position. There are many videos and posts about getting the mouse position, and i tried to use them. My problem is, the mouse position i got is the camera's position, instead of the plane.
As you can see, it is kinda works, but it isn't fall to the plane.
https://prnt.sc/lmrmcl
My code:
void Update()
{
Wall();
}
void Wall()
{
if (Input.GetMouseButtonDown(0))
{
if (Input.GetMouseButtonDown(0))
{
wall = GameObject.CreatePrimitive(PrimitiveType.Cube);
Rigidbody wallsRigidbody = wall.AddComponent<Rigidbody>();
wall.transform.localScale = new Vector3(0.6f, 0.6f, 0.6f);
wallsRigidbody.mass = 1f;
wallsRigidbody.angularDrag = 0.05f;
wallsRigidbody.useGravity = true;
wallsRigidbody.constraints = RigidbodyConstraints.FreezeRotation;
wall.transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
}
Debug.Log(Camera.main.ScreenToWorldPoint(Input.mousePosition));
BoxCollider wallsCollider = wall.AddComponent<BoxCollider>();
wallsCollider.size = new Vector3(1f, 1f, 1f);
}
}
How should i change my code to get the right position?
This isn't a direct answer to your question, but I'm hoping it'll still get you where you need to go.
Prefabs are your friends! I'd highly recommend leveraging them here instead of constructing a cube directly in code.
But first, make sure everything else is set up right. Go ahead and construct a cube by hand in the Editor and make sure that when you hit Play, it falls as you expect. It should, provided it has a Rigidbody, collider, and you have gravity enabled (true by default).
If that works, drag that cube from your Hierarchy view into a folder in the Project view. This creates a prefab. You can now delete the cube from the Hierarchy view.
Update your script to have a public GameObject field, e.g.
public GameObject cubeToCreate;
Then, in the Inspector pane for whatever gameobject has that script attached, you should get a new field, "Cube To Create". Drag your prefab cube into that slot.
Lastly...update your code to wall = Instantiate(cubeToCreate). You'll still need to update the position, but you should be able to drop the rest of the initialization logic you have above, e.g. setting mass and drag.
As for the actual problem, the first thing that concerns me is how do you plan on turning a 2d mouse click into a 3d point? For the axis going "into" the screen...how should the game determine the value for that?
Camera.main.ScreenToWorldPoint accepts a Vector3, but you're passing it a Vector2 (Input.mousePosition, which gets converted to a z=0 Vector3), so the point is 0 units from the camera -- so in a plane that intersects with the camera.
I haven't done this, but I think you'll need to do raycasting of some sort. Maybe create an invisible 2d plane with a collider on it, and cast a physics ray from the camera, and wherever it hits that plane, that's the point where you want to create your cube. This post has a couple hints, though it's geared toward 2D. That might all be overkill, too -- if you create a new Vector3 and initialize it with your mouse position, you can set the z coordinate to whatever you want, but then your cube creation will be in terms of distance from the camera, which is not the best idea.
Hope this helps.