Hi there! Thanks for taking questions. I’m teaching a new game design in Unity course at my school using CodeHS. While making my first 2D skiing game, I created a finish line with a script attached to the finish line parent object that contains tilemap sprites that is supposed to stop the skiier and either send the player of the game to the start screen or to the next slope/level of the game. If followed the tutorial for this script exactly as it was laid out, but my skiier just plows right through the nets at the finish line rather than activate the script. Here is the script… I’d ask them but the guy who made their Unity course no longer works there so yeah. lol
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class FinishLine : MonoBehaviour
{
public TimerManager TimerHud;
public GameObject player;
private Rigidbody2D rb2d;
// Start is called before the first frame update
void Start()
{
rb2d = player.GetComponent<Rigidbody2D>();
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject == player)
{
// Stop player movement on collision
rb2d.gravityScale = 0;
// Call StopTimer() function from timerScript
TimerHud.StopTimer();
// Invoke a method with a delay
Invoke("LoadNextScene", 5f); // Change 5f to your desired delay
}
}
void LoadNextScene()
{
if (SceneManager.GetActiveScene().buildIndex > 1)
{
SceneManager.LoadScene("MenuScreens");
} else {
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}
}
}
Howdy, today’s event focuses on platform specific questions, such as building your games for Windows or WebGL. Your question is about 2D-Physics. I’ve changed the tags in your topic accordingly.
That the gameobjects have colliders properly configured - ensure your collider box is where you expect it to be in playmode (should be doable in gizmo/scene view with the selected gameobject)
Also check you’re using the correct type of detection, collision vs trigger: OnCollisionEnter2D or OnTriggerEnter2D? - a trigger may be more suitable for changing levels.
Hello, good morning, and thank you for the response! I’m going to work with one of my students this morning to try to figure this out and we will use all of your feedback in the process. I’ll let you know how it goes. Thanks again!
Just a heads-up to say that I’m monitoring this thread too. I’m the Unity dev who created the 2D physics here at Unity so I too can help you with any specifics you may need answering.
Great to meet you both! I’m meeting with my student in a few hours. He’s a genius and has helped me (an APCS A & multimedia design teacher tackling Unity & C# for the first time) figure out a bunch of issues so far.
In the meantime, if any of you have a link to best practices for filling in a 2D world using the tile palette or copying/duplicating a scene and adjusting said scene into a new level I’m all ears. I plodded through ski slope one painstakingly slow clicking one square at a time before realizing flood fill was even a thing. lol
Super excited to join the Unity community. I see Unity as a great option for APCS Principles as well in the future.
There’s no one single document that I’m aware of for “best practices for filling in a world” as using tilemaps covers a lot of features both editor and runtime. It all depends on what you’re doing. If you’re just starting then there’s plenty of information on how to start.
I’d start by saying you should first look at the manual for tilemaps which also goes over thew tooling, including the tile-palette and its painting tools: Unity - Manual: Tilemaps in Unity
And beyond that there’s lots of general examples on Youtube for pretty much every aspect of it you can imagine from configuring tiles assets, the layout grid, tile-palette, collision-detection etc.
OK! My student helped me figure out that although I clicked on the Parent finish line object when I added my box collider, the actual collider was only on one of the seven sprites used for the finish line. I clicked edit collider and stretched the collider out over the whole finish line and it worked great. I was transported to my second slope, and at the end of the second slope I was sent back to the menu screen. One last issue though…my slope number for slope 2 still displayed as “slope 1.” Any ideas why that might be? Here is the timer HUD code:
using TMPro; // Include TMPro namespace at top of script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class TimerManager : MonoBehaviour
{
public TMPro.TMP_Text timerText; // Use TMP_Text for TextMeshPro
public TMPro.TMP_Text slopeNumber;
private float elapsedTime;
private bool timerRunning = true;
private Scene currentScene;
// Update is called once per frame
void Update()
{
if (timerRunning)
{
elapsedTime += Time.deltaTime;
int minutes = Mathf.FloorToInt(elapsedTime / 60f);
int seconds = Mathf.FloorToInt(elapsedTime % 60f);
string formattedTime = string.Format(" TIME {0:00}:{1:00}", minutes, seconds);
timerText.text = formattedTime;
}
int sceneIndex = currentScene.buildIndex;
string slope = "SLOPE " + sceneIndex.ToString();
slopeNumber.text = slope;
}
public void StopTimer()
{
timerRunning = false;
elapsedTime = 0.0f;
}
}
Are you 100% positive that the above field in your finish line contains the actual runtime player and not the prefab on disk?
If you drag the prefab into the scene (such that it instantiates automatically at runtime) and also drag the prefab into the field above, when you press PLAY, the one in the scene gets instantiated fresh in the scene, which means that your finish line above is manipulating the “dead” asset on disk.
Those two assets would never be the same at runtime.
Here’s more reading, as well as tips to clean up your naming to remove these sorts of bedeviling ambiguities:
Instancing and prefabs in Unity and naming your variables:
If you name your public / serialized fields (variables) as simply “thing” then you set yourself up for confusion.
If something is a prefab, name it that, such as public GameObject ThingPrefab; and only drag prefabs into it. Prefabs are “dead things (assets on disk) waiting to be Instantiated.”
If something is already in the scene or you Instantiate<T>(); it in code, then store the result in a properly-named variable such as private GameObject ThingInstance;
Naming is hard… name things WELL to reduce your own confusion and wasted time.
See for yourself:
using UnityEngine;
public class PrefabVsInScene : MonoBehaviour
{
public GameObject PlayerPrefab;
public GameObject PlayerInScene;
private void Start()
{
Debug.Log("PlayerPrefab is " + PlayerPrefab.GetInstanceID());
Debug.Log("PlayerInScene is " + PlayerInScene.GetInstanceID());
}
}
I really appreciate this feedback! When I’m done teaching today I’ll try these suggestions out and let you know how it goes. I’m encouraged by how responsive this commUnity is already. I can’t wait to get past the “I don’t even know what I don’t know” phase like I did 15-20 years ago with Photoshop, Illustrator, movie editing, sound engineering, Java, Python, CAD, etc.
Wow. Time flies! I’m nearly at the end of my first semester teaching Game Design & Development in Unity at the high school level and my students and I were able to solve most of the issues that arose except:
(1) The “Slope 1” changing to “Slope 2” issue of the text not changing from 1 to 2 from before, I didn’t fully figure out if the PreFab tips could solve this.
(2) Why do my first 2 yetis move/work, but the additional 2 yetis I added (Yeti 3 & Yeti 4) just stand there and don’t move. If you run into them they “catch you” above their head and roar, but still don’t move.
(3) Why does my first Yeti catch the skier above its head and disable input so you can’t escape, but Yetis 2-4 “let the skier go” and you ski around on your side until the code makes you restart at the top of the slope you were caught in.