OnCollisionEnter is not called - c#

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

Related

Destroy object when it touch Ground unity 2d

Hey I just want my bullet to destroy itself when it touch Ground i tried to destroy after 2 seconds but it has the same problem That's My Code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyBullet : MonoBehaviour
{
GameObject target;
public float speed;
Rigidbody2D bulletRB;
void Start()
{
bulletRB = GetComponent<Rigidbody2D>();
target = GameObject.FindGameObjectWithTag("Player");
Vector2 moveDir = (target.transform.position - transform.position).normalized * speed;
bulletRB.velocity = new Vector2(moveDir.x, moveDir.y);
Destroy(this.gameObject, 2);
}
}
Destroy the bullet object using the Destroy method.The bullet is destroyed after flying a certain distance.
public float speed;
public float destoryDistance;
private Rigidbody2D rg2d;
private Vector3 startPos;
// Start is called before the first frame update
void Start()
{
rg2d = GetComponent<Rigidbody2D>();
rg2d.velocity = transform.right * speed;
startPos = transform.position;
}
// Update is called once per frame
void Update()
{
float distance = (transform.position - startPos).sqrMagnitude;
if (distance > destoryDistance)
{
Destroy(gameObject);
}
}
Use OnCollisionEnter() to destroy to bullet
void OnCollisionEnter(Collision collider)
{
if (collider.GameObject.tag == "Ground")
{
Destroy (this.GameObject)
}
}
What's happening here is that this function gets called every time it collides with an object, so we put the destroy code here. It takes the collider as a parameter, and then checks if the GameObject has the tag "Ground", and if it does, destroy itself.
Note that you will also have to add a tag to your ground objects in the hiearchy. You can name them anything else too, but make sure to change "Ground" in the code when you do set the tag to anything other than it.
You will probably also have other colliders like walls in your game so you should make a universal tag that destroys bullets and name it something like "Destroy Projectiles" or something.
Edit: You can have multiple functions that destroy the GameObject.

How can I make the two cubes to stop when colliding?

Or making them bounce when colliding. but now it's not detecting any collision.
The first cube have a Rigidbody Use Gravity and Is Kinematic both checked enabled true.
If I will disable the Is Kinematic the cube will fall down.
Both cubes have attached the same script.
Both cubes have a box collider and the Is Trigger on both is unchecked disabled.
This script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Door : MonoBehaviour
{
public Transform target;
public float speed;
private void Start()
{
}
private void Update()
{
float step = speed * Time.deltaTime; // calculate distance to move
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
}
}
Each cube have the script and target is the other cube. So both cubes are moving to each other but never collide.
Both cubes settings screenshot :
It would be better practice set rigidbody.velocity once instead of changing transform.position every frame, but this solution should work regardless:
private bool collided = false;
private void Move() {
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
}
private void Update() {
if (!collided) {
Move();
}
}
private void OnCollisionEnter(Collider other) {
if (other.gameObject.GetComponent<Door>() != null) {
collided = true;
}
}
This may not be the best way to do it depending on how you plan on moving forward, but this is a way that works.
If you want to make them bounce, I'd suggest using rigidbody.AddForce() or set rigidbody.velocity. Then you can either use a bouncy physic material or changing the OnCollisionEnter code to use rigidbody.AddForce() or rigidbody.velocity when they collide with each other.

Unity3D Help - Shooting object in direction of player rotation

I'm making a third person sports game and I wish to shoot the ball straight forward from the player.
I have a working script for shooting the ball, however it is attached to the main camera so only shoots in the direction the camera is facing.
I would like to alter this code to attach it to the player instead of the camera.
PS: I am still very new to C#, I assume the problem is in the "camera.main.transform" section but I don't know the code to change it to player.
my code is below;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShootScript : MonoBehaviour
{
public GameObject bulletPrefab;
public float shootSpeed = 300;
Transform cameraTransform;
void Start()
{
cameraTransform = camera.main.transform;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
shootBullet();
}
}
void shootBullet()
{
//Get the Rigidbody that is attached to that instantiated bullet
Rigidbody projectile = GetComponent<Rigidbody>();
//Shoot the Bullet
projectile.velocity = cameraTransform.forward * shootSpeed;
}
}
First of all: You currently do GetComponent<Rigidbody> on that object itself .. this makes no sense since it would fire away "yourself" instead of a bullet. You have to Instantiate a bullet and apply forces/velocity here. You kind of missed the instantiation.
Then simply attach this script to your player Object instead and use transform.forward. transform returns the Transform component of the GameObject this script is attached to.
public class ShootScript : MonoBehaviour
{
// Hint: By making the prefab field Rigidbody you later can skip GetComponent
public Rigidbody bulletPrefab;
public float shootSpeed = 300;
void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
shootBullet();
}
}
void shootBullet()
{
// Instantiate a new bullet at the players position and rotation
// later you might want to add an offset here or
// use a dedicated spawn transform under the player
var projectile = Instantiate (bulletPrefab, transform.position, transform.rotation);
//Shoot the Bullet in the forward direction of the player
projectile.velocity = transform.forward * shootSpeed;
}
}

How do I make my player with a Rigidbody move with isKinematic checked?

My game is a topdown zombie shooter and whenever the zombies get to the player they bunch up underneath them, to the point where the player can just walk over the zombies. I noticed that when I check isKinematic on the Rigidbody the zombies cant push the player up to go underneath him, so they just run into him(which is what I want). Despite this I am then unable to move. How can i fix this?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMoving1 : MonoBehaviour {
public float moveSpeed;
private Rigidbody myRigidbody;
private Vector3 moveInput;
private Vector3 moveVelocity;
private Camera mainCamera;
public GunController theGun;
void Start () {
myRigidbody = GetComponent <Rigidbody>();
mainCamera = FindObjectOfType<Camera>();
}
// Update is called once per frame
void Update () {
moveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical"));
moveVelocity = moveInput * moveSpeed;
Ray cameraRay = mainCamera.ScreenPointToRay(Input.mousePosition);
Plane groundPlane = new Plane(Vector3.up, Vector3.zero);
float rayLength;
if(groundPlane.Raycast(cameraRay,out rayLength))
{
Vector3 pointToLook = cameraRay.GetPoint(rayLength);
transform.LookAt(new Vector3(pointToLook.x,transform.position.y,pointToLook.z));
}
if (Input.GetMouseButtonDown(0))
theGun.isFiring = true;
if (Input.GetMouseButtonUp(0))
theGun.isFiring = false;
}
void FixedUpdate(){
myRigidbody.velocity = moveVelocity;
}
}
With isKinematic == true You can't change object position through rigidbody, You can only change transform.position.
I think it could be better, if You set isKinematic to false and add stopping distance to enemies, so they can't get too close to player.
Being that your player can no longer be effected by the physics engine, you'd have to manipulate the object's transform manually. Your script isn't ideally setup for it currently, but if I was to hack it into it and try to make it work it would look something like this:
(you can change it from fixedUpdate to update if you're no longer utilizing the physics engine)
void update(){
float x = Input.GetAxisRaw("Horizontal")* Time.Deltatime;
float z = Input.GetAxisRaw("Vertical") * Time.Deltatime;
transform.position = new Vector3(transform.position.x+x,0,transform.position.z+z);
Another way of doing this is to lock the position of Y for the player (assuming Y is the positive "up" direction). isKinimatic is best when you want to move the player or objects around yourself.
I would say upping the mass is better in this case, and you can keep isKinematic unchecked in this case then too. Also apply the lock for Y movement (again if it is the "up" direction from the plane)
Let me know what your solution is regardless, I've had some issues in the past as well with these types of events happening

Unity3D - Changing animation states based on movement

I'm trying to make a simple AI (a simple ellipse), which switches between a walking animation and a standing animation, depending on whether or not it is moving.
I already have the AI set to follow and turn to the player, however I am having trouble finding out how to switch between animation states.
I have a Boolean parameter in the animator, "isWalking", which is set to switch to the walk animation if true, and switch to the standing animation if false.
My problem is how to 'check if the object is moving'.
I essentially want to write some code that does something like this:
If(object is moving)
{
isWalking == true;
}
else
{
isWalking == false;
}
I've searched on the web, but I've yet to find a solution.
I considered using rigidbody.IsSleeping() to see if the object is asleep, but I couldn't find any examples of how to use it.
I'm a complete newbie to both Unity and programming.
Thanks in advance. :)
The object, as shown in the inspector window
Edit:
I have tried this code, but there's probably something wrong with it. :/
using UnityEngine;
using System.Collections;
public class aiscript : MonoBehaviour {
NavMeshAgent agent;
public Transform target;
public Animator anim;
Vector3 pos;
public GameObject monmon;
void Start ()
{
pos = monmon.transform.position;
anim = GetComponent<Animator> ();
agent = GetComponent<NavMeshAgent> ();
}
void Update ()
{
pos = monmon.transform.position;
Vector3 originalPosition = pos;
agent.SetDestination(target.position);
Vector3 difference = originalPosition - pos;
anim.SetBool("isWalking", difference.magnitude > 0.5f);
}
}
From the Animator class, you can do that with the GetBool function and also set change the animation state with the SetBool function.
Animator myAnim;
.....
myAnim = GameObject.Find("ObjectAnimatorIsAttachedTo").GetComponent<Animator>();
.....
if (myAnim.GetBool("isWalking") == true)
{
//Is walking.....
}
else
{
//Is not walking
}
You can even change the state of isWalking later on with
myAnim.SetBool("isWalking", false);
myAnim.SetBool("isWalking", true);
I will suppose your object has a Rigidbody attached to it to move, and the Animator.
If so, you just check the velocity vector in the rigidbody, and check it's magnitude to a specific threshold.
Suppose you have a threshold of 0.5f, This will mean that, if the object is moving in any direction at more than 0.5 unit/second, it's considered running, otherwise, it's standing.
Animator myAnimator;
Rigidbody myRigidbody;
void Awake() {
this.myAnimator = GetComponent<Animator>();
this.myRigidbody = GetComponent<Rigidbody>();
}
void Update() {
myAnimator.SetBool("isWalking", myRigidbody.velocity.magnitude > 0.5f);
}
EDIT:
To optimize it, you can save the hash of the boolean parameter of the animator
int isWalkingAnimationId = Animator.StringToHash("isWalking");
and then use that instead of the string.
myAnimator.SetBool(isWalkingAnimationId , myRigidbody.velocity.magnitude > 0.5f);
UPDATE:
It seems you Rigidbody is kinematic, velocity will always be (0,0,0).
I guess you are changing the transform.position manually to move the object. If so:
Vector3 originalPosition = transform.position;
// Your manual changes on transform.position
Vector3 difference = originalPosition - transform.position;
myAnimator.SetBool("isWalking", difference.magnitude > 0.5f);

Categories

Resources