HI, I am new to unity and am trying to create a classic roulette game. I have my wheel and ball moving and and stopping pretty nicely. I just don’t know how to register the number as the winning number once it lands in its spot? Is there anyways to do so? Any help is greatly appreciated
Hi, I suggest you look into collisions in the docs. Unity - Scripting API: Rigidbody.OnCollisionEnter(Collision)
Using collisions you would be able to determine what part of the wheel you are in… And if you had a different object for each number it would be even easier as the ball would tell you which number object it was touching
Thank you for the reply! I have decided to add colliders to the wheel for each “number slot”. The wheel spins for 11 seconds, so I want to wait 11 seconds before the collision will be detected so I know its detecting where the ball is and not just detecting one that it touched while it was being moved around the wheel. I am testing this out by making sure the ball goes into the number 27. Im using the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class collison27 : MonoBehaviour {
public Text textbox;
// Use this for initialization
void Start()
{
StartCoroutine(Example());
}
IEnumerator Example()
{
textbox.text = " ";
yield return new WaitForSeconds(11);
void OnCollisionEnter2D(Collision2D col){
textbox.text = "Landed on 27";
}
}
}
And I am getting the error “Keyword void cannot be used in this context” Any idea why this may be happening?
EDIT: Formatting and wording
You’ve got your braces mixed up.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Collison27 : MonoBehaviour
{
public Text textbox;
// Use this for initialization
void Start()
{
StartCoroutine(Example());
}
IEnumerator Example()
{
textbox.text = " ";
yield return new WaitForSeconds(11);
}
void OnCollisionEnter2D(Collision2D col)
{
textbox.text = "Landed on 27";
}
}
Thank you for the Reply! Your solution got me able to actually run the code but alas it is still saying “Landed on 27” as soon as the ball touches it and is not waiting the 11 seconds. Ugh frustrating. You got me one step closer though thank you!
Oh sorry, didn’t read what you were trying to do. If you want to wait for 11 seconds after the collision then you need to start the coroutine when the collision happens.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Collison27 : MonoBehaviour
{
public Text textbox;
// Use this for initialization
IEnumerator Example()
{
yield return new WaitForSeconds(11);
textbox.text = "Landed on 27";
}
void OnCollisionEnter2D(Collision2D col)
{
StartCoroutine(Example());
}
}
But there is probably a better way to achieve what you’re trying to do. How are you animating the wheel? Are you using physics or is it a pre-made animation?
There are a couple of ideas that come to mind when working with the ideas already part of the thread/discussion here.
-
disable all of the colliders for the spots, until the wheel has stopped, then re-enable them all and you should have your correct enter callback.
-
accept all callbacks and store the name/transform/gameobject that was triggered… however, only check for which one is ‘current’ after the wheel is stopped, and use that to print out the result (and run any other code).
Come to think of it, though, this option may require a little bit of care to be taken, in case a new trigger enter is called but the previous wasn’t left (and the previous is where it ends up ‘landing’).
You could maybe try using a bool to be set when the 11 seconds are up and test that in your collision function.
On a side note using OnCollisionStay might be better too since you want to read the collision when the ball has stopped on the number. You can test it out and see but it may not make a difference.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Collison27 : MonoBehaviour
{
private bool timerFinished = false;
public Text textbox;
// Use this for initialization
void Start()
{
StartCoroutine(Example());
}
IEnumerator Example()
{
textbox.text = " ";
yield return new WaitForSeconds(11);
timerFinished = true;
}
void OnCollisionStay2D(Collision2D col)
{
if(timerFinished)
{
textbox.text = "Landed on 27";
}
}
}
The Idea to disable the colliders were genius. When testing it out I dropped the ball on the spot and it waited 11 seconds before outputting the right result. Once I added all the coliders to the “Number Slots” I tested it out with the wheel spinning and I was surprised to get the wrong output. I am getting the same 3 numbers. I think it is because these numbers are the first ones that the ball hits when spinning. I really don’t understand how they are being hit and registered if they are disabled. This is my code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class colide6 : MonoBehaviour {
public Text textbox;
EdgeCollider2D m_Collider;
float timeleft=11f;
void Start()
{
//Fetch the GameObject's Collider (make sure it has a Collider component)
m_Collider = GetComponent<EdgeCollider2D>();
m_Collider.enabled = false;
}
void Update(){
if (timeleft > 0) {
timeleft -= Time.deltaTime;
} else {
m_Collider.enabled = true;
//Output to console whether the Collider is on or not
Debug.Log ("Collider.enabled = " + m_Collider.enabled);
}
}
void OnCollisionStay2D(Collision2D col)
{
textbox.text = "Landed on 6";
}
}
This code is on a gameobject that has an edge colider on it that corresponds to a number slot. I really appreciate your post.
Just to be sure, are you sure it’s colliding with the ball and not something else?
If you print out the collider’s name, is it correct (the ball?) for the other object?
If you wait until the ball has landed properly, and the time is up, I would think that you could use OnTriggerEnter (or collision, I suppose)… as in you don’t need ‘OnXXXStay’.
Also, you could dispense with colliders completely if you know the final position of the ball relative to the wheel.
Instead of putting that code on each number object have you tried just putting the code on the ball itself? then print out the collider name BUT only print out if the timer is up.
Doing it this way would save you putting a script on each number collider and just on the ball, less is more and all that. Plus it rules out the number colliders colliding with something else and wrong printing out their number.
void OnCollisionStay2D(Collision2D col)
{
if(timeleft == 0)
{
textbox.text = "Landed on "+col.gameObject.name;
// textbox.text = "Landed on "+col.gameObject.tag;
}
}
You could use something like this in the script attached to the ball. It will print out the name of the object it is colliding with, so you could just change the number object names to their respective number. Or you could create separate tags for each object with their numbers in them and change the code to the commented out section.
Edit : added example
To do this would the colliders have to be in the asset of the wheel? If I make a gameobject and make colliders for each number slot, are they gunna rotate with the wheel? If I have to put them on the wheel so it turns how do I name the colliders?
If you make a game object for each number and make them a child of the wheel they should move with the wheel. Just remove the renderers from the objects then they will not be visible so you will just have collider objects.
ps: Just in case, if you don’t know how to make it a child just drag the new object on to the wheel object in the hierarchy window and it will look like a drop down tree.