in the game I am trying to make there is a level with moving platforms that make the player object a child for the duration of the collision.
private void OnCollisionEnter2D(Collision2D collision)
{
collision.transform.SetParent(transform);
}
private void OnCollisionExit2D(Collision2D collision)
{
collision.transform.SetParent(null);
}
Player does have a DontDestroyOnLoad method so he can move between the levels freely. However that method disappears whenever i come into contact with one of the moving platforms so the game crashes while going to the next level because the camera is using the player object to follow him and without player is missing a reference. I am pretty sure that the cause is that it becomes a child object of the platform and the platform itself does not use that method. Is there a way to keep the DontDestroyOnLoad method no matter the circumstances fn the player object?
The scene cannot be loaded automatically. It is controlled by you, so you can unlink the player's parent before switching to the next scene.
player.transform.SetParent(null);
DontDestroyOnLoad(player.gameObject);
SceneManager.LoadScene("next scene");
Related
I am currently learning how to make games in Unity and I want to detect when a Child's collider is being triggered to apply the damage to the thing being hit. But I'm confused about how it works.
Does the Parent's OntriggerEnter detect the trigger event of the Child Object?
And how do I know the trigger comes from the Child and not the Parent?
And which Child's collider got triggered?
The Parent's collider is not triggered but the Child's collider is. Also the Child object doesn't have a rigidbody attach to it
I don't have enough reputation to comment so I'm going to answer it.
It's been answerd here as well I think : Collision Layer Matrix and Parent/Child object relationships.
If the child collision is not inside of parent collision you don't need to set IsTrigger = true for parent collision, just try different layers for you collisions.
Here is Unity documentation : https://docs.unity3d.com/Manual/LayerBasedCollision.html
What you talk about is called self-collision. One way of handling this is to ignore certain colliders, take a look at the documentation here.
If I understood you correctly you have an GameObject hierarchy like so:
parentGO (contains player mesh and Capsule Collider 2D)
|-childGO (contains attack mesh and Mesh Collider 2D)
I'd attach to the childGO a script, which should register collisions on its polygon collider and notify the weapon script on the parentGO of the object being hit. The weapon can then deal the damage to the target.
I know most likely You got your response, but It is also good to mention, that maybe You should think about separating these object and attaching them to new GameObject, that have a script holding both colliders - that might be more reliable and easy to read.
You can use Collider2D.IsTouching(Collider2D other);
Here is documentation for IsTouching
Or write custom script that uses the observer and notify the main GameObject that the collision occurred.
private Action _onGameObjectCollided;
private void OnTriggerEnter2D(Collider2D col){
if(col.gameObject.CompareTag("TAG")
_onGameObjectCollided?.Invoke();
}
public void AddOnColliderEnterObserver(Action observer)
{
_onGameObjectCollided += observer;
}
public void RemoveOnColliderEnterObserver(Action observer)
{
_onGameObjectCollided -= observer;
}
And inside new GameObject:
collider.AddOnColliderEnterObserver(MethodToCallOnTriggerEntered);
I'm developing a simple 2D Unity game (which I'm very new to so sorry if this is a silly question!) in which my player can eat its enemies by colliding with them. This works fine as I'm just selecting the "is trigger" component for the enemies and using this code in my Player class:
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log("Hit detected");
Destroy(other.gameObject);
transform.localScale += new Vector3(x, y, z);
}
However, this means the colliders placed around the border of my background image aren't stopping the enemies. What's the best fix for this?
I don't understand very well your question. However it seems that your collisions are not working. So, remember that for have collisions actually taking place in your game you need to use colliders and that one of the two elements participating in the collision need to have the rigidbody component.
That will make the physics work in the engine, which triggers dont.
To check if that works you can debug with:
// called on collision
void OnCollisionEnter2D(Collision2D col)
{
Debug.Log("OnCollisionEnter2D");
}
From what I understood, you want only to detect triggers between the player and the enemies, but you still want these to collide with physic objects in your scene, such as background colliders.
One possible way to achieve this is to create a child object for the player object with a collider component with the trigger option set, and attaching a script to it to handle the triggers. Then, with the use of layers to group your player and enemy objects, you can uncheck the collision between them following: Edit -> Project Settings -> Physics 2D: "Layer Collision Matrix".
You can assign a script to any enemy, checking the distance with the player in each frame. Then you can Uncheck "is trigger"
Vector2.Distance
So I'm attempting to create a 2D game in Unity where the gameObjects would be destroyed upon hitting the walls. So i decided to use the isTrigger function and add the script to each of the walls. However, I do not know why the gameObjects don't get destroyed. I have tried to set Collision type as both discrete and continuous for the walls and gameobjects and I've also added static rigidbodys to the walls to see if that would help and even tried changing the size of the collisionbodys of the walls.
Here is the code for the wallscript
public class wallScript : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void OnTrigger2D(Collider2D other)
{
if (other.tag == "player01")
{
Destroy(other.gameObject);
}
}}
p.s. Even if I remove the conditional statement Destroy() still does not work
You should use void OnCollisionEnter2D(Collision2D other) {...} instead of void OnTrigger2D(Collider2D other).
And uncheck Is Trigger checkbox on your object's Collider.
To Fix The Problem You Are Facing, First Select The Wall Sprite In The Scene, Scroll Down To The Collider And Make Sure Is Trigger Is Checked.
Other Than That Just Check If The Tag You Typed Into The Code Matches The Player You Are Trying To Destroy. Remember, It's Case Sensitive!
After That The Code Should Run Just Fine.
Right now, I have a multiplayer game where the player fires projectiles at other players that have a certain amount of bubbles. Once a player has lost all of their bubbles, they lose.
The issue I had previously was that on one screen, a first player could shoot out a second player's bubbles, but not all of the bubbles on the second player's screen would be popped, so I am trying to sync it over the network somehow.
The issue I'm seeing is that NetworkServer.Destroy requires finding the GameObject you intend to destroy by its NetworkIdentity, but only the root Player GameObject is allowed to have the NetworkIdentity component on it. What's the best way I can sync the destruction of a child object of a player?
The https://unity3d.com/fr/learn/tutorials/topics/multiplayer-networking/ course is very similar to the game you describe. It has a Bullet script attached to the fired bullets. If the bullets touched something, it check if it's a player, and apply damage to it (the player prefab has a Health script attached to it).
using UnityEngine;
using System.Collections;
public class Bullet : MonoBehaviour {
void OnCollisionEnter(Collision collision)
{
var hit = collision.gameObject;
/* Code below is from the original example
var health = hit.GetComponent<Health>();
if (health != null)
{
health.TakeDamage(10);
}*/
var bubble = hit.GetComponent<BubbleBehavior>();
if (bubble != null)
{
bubble.Popped(); // Implement a Popped function doing the magic
}
Destroy(gameObject);
}
}
In your case you can do the same, but instead of checking if the touched object is a player, simply check if it is a bubble, and do whatever you want from the touched bubble.
In the original example, they sync the health (it is a "SyncVar"), in your case you can sync the number of bubbles remaining.
I'm trying to switch a scene over the network and i want each player to locally load the scene Async so that everyone can get a loading screen. I'm struggling with Command and RPC calls. After the scene changes i would like to respawn a new player and associate it with the client.
public void changeLevel(string name)
{
CmdChangeLevel(name);
//nm.ServerChangeScene(name); -> This doesnt change the scene Async
}
void changeScene(string name)
{
SceneManager.LoadScene(name);
//Stuff to re-Instantiate the player
}
[Command]
void CmdChangeLevel(string name)
{
SceneManager.LoadScene(name);
RpcChangeLevel(name);
}
[ClientRpc]
void RpcChangeLevel(string name)
{
changeScene(name);
}
Everything i tried resulted in a scene switch but no players instantiated, like (nm = networkManager) nm.OnServerAddPlayer() and instantiate it then spawn it through the server. Help would be much appreciated, thanks in advance
Perhaps what you need is a static gamemanager with DontDestroyOnLoad (DDOL)?
Basically what you do is:
1) Create a scene and put it first in your game build order (so game first load in to it)
2) Create an empty GameObject with a GameManager script. In Start() put the DontDestroyOnLoad-method.
3) In your script, load your "first" scene (main menu or splash screen or whatever)
This will make the Object you put your DDOL-script to stay even between scene changes, so you could handle the loading screens and player spawns etc in that gameobject.