How do I snap an object with a rigidbody when it gets hit by a box collider?
The object needs to be snapped to a position when it enters a collider.
I have tried to make it happen but as soon as the box enters the collider, the object gets thrown away.
Thanks, I did it using Box Collider itself. here is the working code, it works now:
public class SnapModelToPosition : MonoBehaviour {
public Rigidbody rb;
Vector3 newPos = new Vector3(0.1192573f, -0.630803f, 0.02599394f);
// Use this for initialization
void Start () {
rb.GetComponent<Rigidbody>();
}
void OnCollisionEnter(Collision col)
{
if(col.gameObject.name == "SnapToPosition")
{
Destroy(rb);
this.transform.localPosition = newPos;
this.transform.localEulerAngles = new Vector3(0, -90.00001f, 0);
}
}
}
Related
I am a beginner in Unity and I am currently making a simple game. I have a problem where upon initial collision, the event that I wanted to happen does not trigger or in other words the OnCollisionEnter is not working upon initial collision.
The process of my script is when colliding which is the OnCollisionEnter the button will appear or it will be set active to true. But in the first collision it does not trigger or it is not working, I need to walk away a bit and go back in that way it only works. Sometimes I need to do it 2 or more times for the collider to trigger. I don't know if the script has problem or the collider itself but I made sure it is colliding properly when I look at the editor.
I set the object to static so it will not be pushed when walking and colliding towards it. I wonder if that has to do with this problem because even disabled it is the same. But can anyone give suggestions on how not to make the objects move or be pushed away upon collision?
Here is the script for my collision:
using UnityEngine;
using UnityEngine.UI;
public class InteractNPC : MonoBehaviour
{
//public Button UI;
[SerializeField] GameObject uiUse, nameBtn;
private Transform head;
private Vector3 offset = new Vector3(0, 1.0f, 0);
// Start is called before the first frame update
void Start()
{
//uiUse = Instantiate(UI, FindObjectOfType<Canvas>().transform).GetComponent<Button>();
uiUse.gameObject.SetActive(true);
head = transform.GetChild(0);
uiUse.transform.position = Camera.main.WorldToScreenPoint(head.position + offset);
}
// Update is called once per frame
void Update()
{
uiUse.transform.position = Camera.main.WorldToScreenPoint(head.position + offset);
nameBtn.transform.position = Camera.main.WorldToScreenPoint(head.position + offset);
}
private void OnCollisionEnter(Collision collisionInfo)
{
//Debug.Log("wews2");
if(collisionInfo.collider.name == "Player")
{
nameBtn.gameObject.SetActive(true);
}
}
private void OnCollisionExit(Collision collisionInfo)
{
if(collisionInfo.collider.name == "Player")
{
nameBtn.gameObject.SetActive(false);
}
}
}
Here is another script with collision and has the same problem:
using UnityEngine;
using UnityEngine.UI;
public class InteractButtonPosition : MonoBehaviour
{
//public Button UI;
[SerializeField] GameObject uiUse;
private Vector3 offset = new Vector3(0, 0.5f, 0);
// Start is called before the first frame update
void Start()
{
//uiUse = Instantiate(UI, FindObjectOfType<Canvas>().transform).GetComponent<Button>();
//uiUse = GameObject.FindGameObjectWithTag("ViewButton");
}
// Update is called once per frame
void Update()
{
uiUse.transform.position = Camera.main.WorldToScreenPoint(this.transform.position + offset);
}
private void OnCollisionEnter(Collision collisionInfo)
{
if(collisionInfo.collider.name == "Player")
{
Debug.Log("wews");
uiUse.gameObject.SetActive(true);
}
}
private void OnCollisionExit(Collision collisionInfo)
{
if(collisionInfo.collider.name == "Player")
{
//Destroy(uiUse.gameObject);
uiUse.gameObject.SetActive(false);
}
}
}
Try changing Colision detection from Descrete to Continuous
collission detection
I solved this issue by using OntriggerEnter instead of OnCollisionEnter. In the editor, for the NPC I put a Collider on each part of the body and check the IsTrigger in the parent Object so it will still collide with my character even if the IsTrigger is enabled that will make the character go through the object. I just enlarged the scale of the collider with IsTrigger enabled so the collision will be detected immediately.
I need some help with Unity.
I try to make an object to detect a collision, but for some reason, the OnColissionEnter function is not called.
Both my objects have rigidBody and Box Collider attached, isTrigger is unenabled as well.
I supposed it's because I have AddForce in my code, but I am not sure. Have anybody a clue what is going wrong there?
Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cuplat2 : MonoBehaviour
{
public Vector3 Target = new Vector3();
private Rigidbody rb;
public float thrust;
private void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
Vector3 NewPosition = transform.position + Target;
Vector3 Position = transform.position;
if (transform.position.x < Target.x)
{
rb.AddForce(transform.position * thrust);
}
else
{
//rb.isKinematic = true;
}
}
public void OnCollisionEnter(Collision collision)
{
Debug.Log("stop");
if (collision.gameObject.name == "Cupla T2")
{
Debug.Log("stop");
}
}
}
One of your rigidbodies has to have isKinematic = false;
If it's not possible in your case I see they have workaround for that:
https://forum.unity.com/threads/collision-detection-for-kinematic-rigidbodies.885778/
Other option would be that the collision is disabled in collision layer mask, but that would cause objects to pass trough each other (I believe that's not the case)
Third option: your rigidbody does not have collider (maybe collider is on parent, has enabled = false, or inactive game object?)
Fourth option: If your object moves very fast you should change Collision Detection Mode to Continous Dynamic
How about the collision layer matrix? Go into Edit > Project Settings, then select the Physics. Check if the layers set to the GameObjects are actually having any collision between them. Collision Layer matrix
I'm making a top-down game where you drive a car and shoot targets at the same time. I have a script that makes a sprite of a crosshair follows the mouse cursor and I want to have it set up so that when the player presses the mouse button (the mouse button isn't in the code now) and the crosshair sprite is overlapping an enemy sprite, the enemy dies. I was following this documentation on Bounds.Intersects. Here's my code:
public class shootingScript : MonoBehaviour
{
public GameObject target, enemy;
CircleCollider2D targetCollider;
CapsuleCollider2D enemyCollider;
// Start is called before the first frame update
void Start()
{
//Check that the first GameObject exists in the Inspector and fetch the Collider
if (target != null)
{
print("targ not null");
targetCollider = target.GetComponent<CircleCollider2D>();
}
//Check that the second GameObject exists in the Inspector and fetch the Collider
if (enemy != null)
{
print("enemy not null");
enemyCollider = enemy.GetComponent<CapsuleCollider2D>();
}
}
// Update is called once per frame
void Update()
{
if (targetCollider.bounds.Intersects(enemyCollider.bounds))
{
print("hit");
Destroy(enemy);
}
}
}
In-game "targ not null" and "enemy not null" prints but when I move my cursor and the crosshair goes over the enemy "hit" is not printed and the enemy is not destroyed. I have a CircleCollider2D on the crosshair and a CapsuleCollider2D on the enemy. The script is on an empty game object. I also tried sprite.bounds but that resulted in the enemy getting killed as soon as I run the game.
EDIT:
Here's the code that keeps the crosshair sprite on the cursor. I copied it from somewhere. I set moveSpeed to 99999 since I want the crosshair sprite to be exactly where the mouse is.
public class mouseReticle : MonoBehaviour
{
private Vector3 mousePosition;
public float moveSpeed = 0.1f;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
mousePosition = Input.mousePosition;
mousePosition = Camera.main.ScreenToWorldPoint(mousePosition);
transform.position = Vector2.Lerp(transform.position, mousePosition, moveSpeed);
}
}
The target sprite and enemy sprite were at different depths (z).
I can't manage to instantiate a prefab at my mouse position.
I've tried to instantiate the prefab at the current mouse position, but on click, the block shows in the hierarchy and not the scene. It also creates 4-5 prefabs.
using UnityEngine;
public class Building : MonoBehaviour
{
public GameObject block;
void Update()
{
if (Input.GetMouseButton(0))
{
Instantiate(block, new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0f), Quaternion.identity);
}
}
}
I want to create 1 prefab of the block, and I want it to show up in the scene view.
Input.mousePosition is the coordinates of the mouse on the screen. Use Camera.ScreenToViewportPoint to get the world position.
The block will not show in the scene, because its position is likely something like (500, 300, 0), which is very far. Select the block in the Hierarchy and press "F" to see it.
Input.GetMouseButton() keeps firing as long as the mouse is held. Change this to Imput.GetMouseButtonDown()
using UnityEngine;
public class Building : MonoBehaviour {
public GameObject block;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition);
Instantiate(block, pos, Quaternion.identity);
}
}
}
You need to convert from screen space to world space.
One way to do this is to use Camera.ScreenToWorldPoint:
private Camera mainCam;
void Start()
{
mainCam = Camera.main;
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Vector3 blockPos = mainCam.ScreenToWorldPoint(Input.mousePosition);
Instantiate(block, blockPos, 0f), Quaternion.identity);
}
}
If you want to spawn further away from the camera, look into Camera.ScreenPointToRay.
I have a prefab empty object that contains the rotating cube. I was trying to do the technique here: https://answers.unity.com/questions/356438/how-to-stop-a-collider-rotating-with-the-gameobjec.html . I have a proper tag, the onTrigger checkbox is checked.
FoodGenerator
public class FoodGenerator : MonoBehaviour {
public GameObject food;
public int foodCount;
void Start () {
for (int i = 0; i < foodCount; i++){
Vector3 position = new Vector3(Random.Range(-8.0f, 8.0f), 1.0f, Random.Range(-8.0f, 8.0f));
Instantiate(food, position, Quaternion.identity);
}
}
}
NonRotatingCollider
public class NonRotatingCollider : MonoBehaviour {
private void OnTriggerEnter(Collider other)
{
Debug.Log("Triggered", other);
if (other.gameObject.CompareTag("Pick Up"))
{
Vector3 position = new Vector3(Random.Range(-8.0f, 8.0f), 1.0f, Random.Range(-8.0f, 8.0f));
transform.position = position;
}
}
}
The Debug.Log("Triggered") here does not even activate. What am I doing wrong?
If you want the OnTriggerEnter function to be called, the isTrigger property must be enabled on the collider. Also, a Rigidbody must be attached to the collider. There is no evidence you've attached Rigidbody to the GameObject. If Rigidbody is already attached this GaeObject, make sure that isKinematic is not enabled on both colliding Rigidbodies.
OnTriggerEnter should be called when none or just one of the colliding Rigidbody has isKinematic enabled. If both colliding Rigidbody has isKinematic enabled, OnTriggerEnter will not be called.