onCollsionEnter specifying objects? - unity3d

I'm currently making a infinite runner type game for a class project and I need some help with collisions.
The game is set up as a 2d platform where a character is running (or made to look like they're running with a scrolling texture) through an infinite tunnel. The player has to avoid obstacles similar to Flappy Bird using jumps. The script I'm using at the moment is setup so that when the player collides with obstacles the game will reload.
The issue:
The issue is that the code I've used applies to all collisions so when the player hits the ground platform the game reloads.
What I want to happen:
I want the character to be able to run on a platform and die when he hits the a specific obstacle.
So I'm think I need to specify a GameObject to collide with?
This is my current code:
// Update is called once per frame
void Update ()
{
// Jump
if (Input.GetKeyUp("space"))
{
rigidbody2D.velocity = Vector2.zero;
rigidbody2D.AddForce(jumpForce);
}
// Die by being off screen
Vector2 screenPosition = Camera.main.WorldToScreenPoint(transform.position);
if (screenPosition.y > Screen.height || screenPosition.y < 0)
{
Die();
}
}
// Die by collision
void OnCollisionEnter2D(Collision2D other)
{
Die();
}
void Die()
{
Application.LoadLevel(Application.loadedLevel);
}
}

Use tags. For example, use a terrain tag for the ground. If the object tag is terrain, then don't die.
Here is a simple example:
void OnCollisionEnter2D(Collision2D other)
{
if (other.collider.tag == "Terrain")
{
Debug.Log("Don't die!");
}
else
{
Debug.Log("Die!");
}
}

Related

Movement stops whenever player touches ground

I am trying to learn the basics of unity collision and I want the movement of the player to stop whenever it touches an obstacle but the movement stops whenever it touches the ground. I tagged the obstacle with a tag called obstacle and left the ground untagged but whenever the player touches the ground it stops all movement. Does anyone know how to fix this? Heres my code: `using UnityEngine;
public class PlayerCollision : MonoBehaviour
{
public Movement playerMovement;
void OnCollisionEnter(Collision collisionInfo)
{
Debug.Log(collisionInfo.collider.tag == "Obstacle");{
playerMovement.enabled = false;
}
}
}
The code you've written stops the movement of the player whenever its collides with something. The code wouldn't even compile because of the "{" at the end.
void OnCollisionEnter(Collision collisionInfo)
{
// returns true or false in the console depending on whether player its colliding with the obstacle
// code won't compile because of the "{" at the end
Debug.Log(collisionInfo.collider.tag == "Obstacle");{
playerMovement.enabled = false;
}
To fix that you can use an if statement and remove the "{" at the end like shown below.
It is also recommended to use CompareTag when working with tags.
void OnCollisionEnter(Collision collisionInfo)
{
if(collisionInfo.collider.CompareTag("Obstacle"))
{
playerMovement.enabled = false;
}
}

Can't detect collision with child and ground

I have the below script attached to the ground game object to detect collisions from my players' child objects but for some reason, the collisions are not detecting.
My player (parent, empty game object) has a Rigidbody and Jump script attached to it, meanwhile, the child game objects (body & feet) have just box colliders on them.
Would love to know why this isn't working :)
private void OnCollisionEnter(Collision collision)
{
if(collision.gameObject.tag == "Body")
{
Debug.Log("Game over!");
}
else if (collision.gameObject.tag == "Feet")
{
Debug.Log("Alive!");
}
}
For some reason, it works when you do collision.collider.tag instead of collision.gameobject.tag, like so:
if(collision.collider.tag == "Head")
{
Debug.Log("Game over!");
}
Not exactly sure why this works, but it works! Defo going to look into this a bit more.

AddForce() not working on velocity-synced object over PhotonNetwork

I have a player object which has (along with other components and objects) a Rigidbody2D, a Collider2D, a PhotonView, and a script called "PhotonLagCompensationView" attached to it. PhotonLagCompensationView syncs the position and velocity of the attached Rigidbody2D, and applies lag compensation like so:
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
if (stream.IsWriting)
{
stream.SendNext(rigidBody2D.position);
stream.SendNext(rigidBody2D.velocity);
}
else
{
networkedPosition = (Vector2)stream.ReceiveNext();
networkedVelocity = (Vector2)stream.ReceiveNext();
float lag = Mathf.Abs((float)(PhotonNetwork.Time - info.SentServerTime));
networkedPosition += networkedVelocity * lag;
}
}
void FixedUpdate()
{
if (!photonView.IsMine)
{
rigidBody2D.velocity = networkedVelocity;
rigidBody2D.position = Vector2.Lerp(
rigidBody2D.position, networkedPosition, Time.fixedDeltaTime * interpolateRate);
}
}
The issue is when I try to call Rigidbody2D.AddForce() on that GameObject, the velocity wont even stutter. What blows my mind about this though is that when I call the EXACT SAME FUNCTION on a different script, it works just fine on all players in the room.
The script that is not working is "KnockBackOnTrigger" which is attached to an object which is instantiated over the network by the player. This object has a Collider2D which is a trigger, and a PhotonView. The OnTriggerEnter2D callback is working just fine. It prints "trigger", and I've even Debug.logged the AddForce() parameters, and a TryGetComponent<>() to make sure the Rigidbody is being recognized and it's applying force properly. The script applies force like this:
void OnTriggerEnter2D(Collider2D collider)
{
if(collider.gameObject.layer == 9 && collider.gameObject != PlayerManager.LocalPlayerInstance)
{
Debug.Log("trigger");
collider.gameObject.GetComponent<Rigidbody2D>().AddForce(
new Vector2(this.transform.localScale.x * knockBackForce, 0),ForceMode2D.Impulse);
}
}
Triggers show up, Rigidbody2D shows up, no moveme
The script that is working is a script attached to the "Lava Blocks" Gameobject which is a tilemap object. The tilemap object for the lava blocks has all the tilemap components attached to it (map, renderer, collider) and they work as intended, as well as the script attached to it. The "LavaBlocks" script works like this:
void OnCollisionEnter2D(Collision2D collision)
{ // everything inside this statement will happen to the player when it touches lava.
if (collision.gameObject.layer == 9)
{
collision.gameObject.GetComponent<Rigidbody2D>().AddForce(
Vector2.up * upwardForce, ForceMode2D.Impulse);
}
}
So whenever a player touches one of the Lava tiles' collider, it bounces upward.
Additionally, I've tried setting the velocity of the Rigidbody2D, which did not work either. This is in fact what I originally wanted to do with the script, but I tried AddForce() to see if that would work.
At one point I even tried to just use the player's CharacterController2D.Move() function to just smack the player's position some units to the left/right, and even this did not do anything.

Transmiting a parameter in multiplayer

I am working on a Unity 2D fps multiplayer game. Whenever a player presses Space they instantiate a bullet and when a bullet hits any player it has to destroy itself and push the player in the bullet direction. My code looks like this:
void OnTriggerEnter2D(Collider2D col)
{
if (isServer == false)
return;
if (col.gameObject.tag != "bullet")
return;
CmdTrigger(col.gameObject);
}
[Command]
void CmdTrigger(GameObject col)
{
RpcTrigger(col);
}
[ClientRpc]
void RpcTrigger(GameObject col)
{
Rigidbody2D rb;
rb = col.GetComponent<Rigidbody2D>();
if (rb.velocity.x > 0)
RpcExplode(Mathf.Sign(1));
else
RpcExplode(Mathf.Sign(-1));
//Network.Destroy(col);
}
The problem is that when a bullet collides a player I can't transmit well the GameObject to the other players so every player can destroy the bullet on their client. When a bullet hits a player it doesn't destroy itself, it just passes through and the Console shows me this error: "NullRefrenceException: Object reference not set to an instance of an object", and if I click on it, it brings me to this line:
rb = col.GetComponent<Rigidbody2D>();
Here is my character control full code: https://pastebin.com/L1DEmQv1
Any ideas? It is very important for me to fix it as soon as possible. Thanks.

UNITY Lose one life when player hits the water

I want to change the number of lives every time the player hits the water. I wrote this code so far:
public var dieSound:AudioClip;
static var lives = 3;
function Start () {
}
function Update () {
if(lives == 0)
{
Application.LoadLevel("menu");
}
}
public function OnGUI()
{
GUI.backgroundColor = Color.blue;
GUI.Button (Rect (10, 10, 100, 30), "Lives: " + lives);
}
function OnControllerColliderHit (hit : ControllerColliderHit)
{
if (hit.collider.tag == "Water")
{
// play dying sound
audio.PlayOneShot(dieSound);
// show mission fail UI
GameObject.Find("MissionTXT").guiText.enabled = true;
// wait until it's ended
yield WaitForSeconds(dieSound.length + 0.01);
transform.position = GameObject.FindWithTag("Respawn").transform.position;
if (transform.position == GameObject.FindWithTag("Respawn").transform.position)
{
GameObject.Find("MissionTXT").guiText.enabled = false;
lives = lives - 1;
}
}
}
The problem is that when the player hits the water, lives change from 3 to -120. I think that happens because the player is on the water for like 6-7 seconds. So character may hits the water 120 times until he goes back to the original position (Respawn position).
Can anyone help me with that please?
The first thing that comes to mind is as follows:
On your water GameObject, add a Collider component. I would think that a BoxCollider would fit in this scenario. Don't forget to mark the Is Trigger checkbox.
On your player GameObject, add both a RigidBody and a CharacterController (since it looks like you are using the CharacterController component). Make sure to check the RigidBody's Is Kinematic checkbox. Also, give your GameObject a meaningful tag like "Player".
Back to the water GameObject, add a new script that should look something like this:
public class Water : MonoBehaviour {
void OnTriggerEnter(Collider collider) {
if(collider.CompareTag("Player")) {
collider.SendMessage("Kill");
}
}
}
Back to the player GameObject, add a new script that should look something like this:
public class Player : MonoBehaviour {
public void Kill() {
//Perform all necessary steps to kill the player such as...
//Reduce the amount of lives by 1
//Play the death sound
//etc. etc. etc.
}
}
That's the "jist" of things, or this should at least get you started. Unity has some really good documentation and practically anything you need is there, you just have to know where to look. I'm not going to go in-depth of each thing I have mentioned above because as I've said, "Unity has some really good documentation." With that in mind, I highly recommend looking into each of the things I have mentioned. Hope this helps! =)