I am new to Unity and am trying to create a 2D game where you can throw snowballs to a snowman. So far I’ve created 2 characters; a player and a snowman. Both are multi layered .psb-files. The player is all rigged and animated; getting a snowball from a pile of snowballs and a throwing animation.
I’ve added the snowman to the scene and gave a RigitBody2D and a Collider2D to each layer/child component; hat, head, upper body and lower body. I was thinking to create one C#-script to handle the collisions. See the code below. It is just that the OnCollisionEnter2D is only triggered for the parent component, not the child component. Is there a nice way to handle this all in the snowman class file in stead of creating one file for each child? (The reason I like to handle each child component separately is so they can fall of the component below it as soon as they are hit, in stead of the whole snowman falling over at once.
Also, because of the way the way the body parts are stacked on top of each other, I start with isKinematic = true for each child component. It has to be set to false as soon as a collisions has happened for just that component (and maybe the ones above). If it is set to false from the start, the snowman will collapse right away.
Thank you all any tips!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Snowman : MonoBehaviour
{
Rigidbody2D _rigidbody2D_Hat;
Rigidbody2D _rigidbody2D_Head;
Rigidbody2D _rigidbody2D_UpperBody;
Rigidbody2D _rigidbody2D_LowerBody;
private void Awake()
{
_rigidbody2D_Hat = GameObject.Find("Hat").GetComponent<Rigidbody2D>();
_rigidbody2D_Head = GameObject.Find("Head").GetComponent<Rigidbody2D>();
_rigidbody2D_UpperBody = GameObject.Find("UpperBody").GetComponent<Rigidbody2D>();
_rigidbody2D_LowerBody = GameObject.Find("LowerBody").GetComponent<Rigidbody2D>();
}
// Start is called before the first frame update
void Start()
{
_rigidbody2D_Hat.isKinematic =
_rigidbody2D_Head.isKinematic =
_rigidbody2D_UpperBody.isKinematic =
_rigidbody2D_LowerBody.isKinematic = true;
}
// Update is called once per frame
void Update()
{
}
private void OnCollisionEnter2D(Collision2D collision)
{
Debug.Log("Collided!");
}
}
I believe you’ll need a script for each child object, as the collision is called on each separately when hit. But you can make just one script file and re-use it by having the collision simply tell the parent script “hey, a snowball hit me, and I’m _____ object” (just send it the gameObject name, because you’ve already named them uniquely). Then you can handle all the logic in the parent script if you want to organize it that way, which I recommend.
There may be other ways though, like using Events, not sure.
On the snowball is a good idea. I’m a little confused about the currentCollider = “” though, if there are multiple snowball instances, that will continue to get set to “”, and it looks like you want it to persist across throws? Maybe you’re reusing the snowball though, in which case that would work.
You can also eliminate the variable for colliderRB2D if all you’re doing is setting isKinematic to false:
collision.rigidboby.isKinematic = false;
However, if you need to do other things with it, then it’s good to have a variable to hold it like you do.
Not sure if it makes a difference, but if I understand you correctly, it does. I could (or should?) change the = “” to an extra if statement at line 16 to check if currentCollider != null.
I might also go a script per “body part” of the snowman, as you suggested, because there are some funny things that can happen to parts that are hit by other parts. The snowball is disabling the “isKinematic”. If a part is hit by an other part, it sometimes flies into the air, because it gets a force/velocity, but it is still “weightless”.
Looks cool!
Playtesting should determine how to set the scripts on the other parts, definitely try every extreme case you can.
I don’t see a reason for the SetKinematic method, I would just do it right on the rigidbody (also you have a second argument that’s always false, so not really needed). In fact, you can just use one line (at line 38), and no childColliderRB2D variable: