I am new to unity as a whole and decided to create small simple snake game as a test. I managed to create movement, the problem now is I want to eat the apple first, then wait till I eat the apple, then spawn a new one.
So far I managed to make it wait till I eat the first apple but then it spawns a lot of apples all at once, how do I make it that It waits till I eat the apple then spawns one apple and then another apple so far and forth.
I made only 1 apple spawn in a set location so far because I wanted to test it out before spawning in another location.
Here is the code I got so far
void OnTriggerEnter2D(Collider2D other)
{
Destroy(gameObject);
}
public void checkApple()
{
if (GameObject.Find("Apple"))
{
Debug.Log("The apple has not been eaten");
}
else
{
Debug.Log("The apple has been eaten!");
GameObject a = Instantiate(Apple) as GameObject;
a.transform.position = new Vector2(-10.26f, 3.66f);
}
}
void Update()
{
checkApple();
}
While there are better methods to handle your problem than to search your entire scene for an object name a solution to your problem would look as followed:
Currently you instantiate a new Object after you destroyed the old one, while your prefab or object might be called "Apple" the new Instance will be called "Apple(Clone)" and as you are only searching for the object that is called "Apple" and not for an object that contains the name Apple it will never find an object.
To avoid that you would need to set the name of the newly created object. For that you only need to rename the created object
if (GameObject.Find("Apple"))
{
Debug.Log("The apple has not been eaten");
}
else
{
Debug.Log("The apple has been eaten!");
GameObject a = Instantiate(Apple) as GameObject;
a.name = "Apple";
a.transform.position = new Vector2(-10.26f, 3.66f);
}
However if your final goal is to "create a new apple on a new position" it would be better to just move the object to the new position when your snake collides with the apple, if you dont want the apple to instantly spawn you could create a cooldown timer something like this:
void OnTriggerEnter2D(Collider2D other)
{
//when needed make sure that the snake only eats apples
//if(other.name.Equals("Apple")){
//for a random position you could use
// Apple.transform.position = new Vector2(Random.Range(-10.0f, 10.0f),Random.Range(-10.0f, 10.0f));
Apple.transform.position = new Vector2(-10.26f, 3.66f);
Apple.SetActive(false);
cooldown = 2f;
inactiveApple = true;
//}
}
public void checkApple()
{
cooldown -= Time.deltaTime;
if(cooldown <= 0 && inactiveApple)
{
Apple.SetActive(true);
inactiveApple = false;
}
}
Of course in the end you would need to check first if the new position is occupied by the snake befor you spawn it there, but that's off topic.
You can use invoke to wait;
float waitingTime = 1f;
void Start()
{
Spawn();
}
void OnTriggerEnter2D(Collider2D other)
{
Destroy(gameObject);
Invoke("Spawn", waitingTime);
}
void Spawn()
{
Debug.Log("The apple has been spawned!");
GameObject a = Instantiate(Apple) as GameObject;
a.transform.position = new Vector2(-10.26f, 3.66f);
}
Related
THIS POST IS NOW IRRELEVANT PLEASE CHECK MY NEWER ONE
I am making a horror game with next bots on VR (Quest/Quest2)
the player has 1 "Mixed" light on it and the bots use pathfinding AI with navmeshes and stuff but it seems that when the next bot gets within I'll say like 10 feet of the player and the player can see it and all the game just decides it wants to freeze and stop working!
It seems to happen before the player "Dies" but I'm not fully sure.
public class Kill : MonoBehaviour
{
// Start is called before the first frame update
public GameObject tes;
public GameObject LocoToOff;
public Vector3 SPOT;
public GameObject SprintLoco;
public GameObject Dead;
public AudioSource audioSource;
private bool Using;
public GameObject Safe;
public LocomotionControllery Loco;
private bool ChillOutItsGoing;
IEnumerator TurnOff()
{
ChillOutItsGoing = true;
LocoToOff.SetActive(false);
SprintLoco.SetActive(false);
Dead.SetActive(true);
Loco.Disabled = true;
audioSource.Play();
yield return new WaitForSeconds(3);
//foreach (var pls in WallsNStuff)
//{
// pls.SetActive(false);
//}
tes.transform.position = SPOT;
//yield return new WaitForSeconds(0.05f);
Loco.Disabled = false;
Dead.SetActive(false);
//foreach (var pls in WallsNStuff)
//{
// pls.SetActive(true);
//}
Safe.SetActive(true);
ChillOutItsGoing = false;
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "BOT")
{
if (ChillOutItsGoing == false)
{
Debug.Log(other.gameObject.name);
Using = LocoToOff.active;
StartCoroutine(TurnOff());
}
}
}
}
I believe it ended up just being because the thing was set to "Cutout" instead of opaque and Cutout I think is in alpha only 2 things I changed that fixed it for sure was setting it to opaque and adding a lil bit of smoothness (just did that idk if it was part of the fix or not)
How to make the end of the game in pakman when all the dots have been eaten?
This is the end game code now
void OnTriggerEnter2D(Collider2D co)
{
if (co.name == "PacMan")
{
Destroy(co.gameObject);
EndMenu.SetActive(true);
GameObject.Find("EndGameConvas/EndGamePanel/Score").GetComponent<Text>().text = GameObject.Find("Canvas/Score").GetComponent<Text>().text;
Time.timeScale = 0;
}
}
This is the point eating code
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.name == "PacMan")
{
Destroy(gameObject);
GameObject.Find("Canvas/Score").GetComponent<Score>().ScoreChange(1);
}
}
If what you're asking is "how do I let the game know the level is over and trigger the end" then just have a variable to hold how many dots are in the level, and every time you eat one and that trigger collider fires, have a counter go up. When the counter equals the total, level ends.
In your class for the dots you could use something like
public class YourDotClass : MonoBehaviour
{
// Keeps track of all currently existing instances of this class
private readonly static HashSet<YourDotClass> _instances = new HashSet<YourDotClass>();
private void Awake ()
{
// Register yourself to the instances
_instances.Add(this);
}
private void OnDestroy ()
{
// Remove yourself from the instances
_instances.Remove(this);
// Check if any instance still exists
if(_instances.Count == 0)
{
// => The last dot was just destroyed!
EndMenu.SetActive(true);
GameObject.Find("EndGameConvas/EndGamePanel/Score").GetComponent<Text>().text = GameObject.Find("Canvas/Score").GetComponent<Text>().text;
Time.timeScale = 0;
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.name == "PacMan")
{
Destroy(gameObject);
GameObject.Find("Canvas/Score").GetComponent<Score>().ScoreChange(1);
}
}
}
However, you should really rethink/restructure your code and think about who shall be responsible for what.
Personally I would not like the dots be responsible for increasing scores and end the game .. I would rather have a component on the player itself, let it check the collision, increase its own points and eventually tell some manager to end the game as soon as all dots have been destroyed ;)
I think you could use something like this. Just store all of the pacdots in an array and once the array is empty you could end the game.
GameObject[] pacdots = GameObject.FindGameObjectsWithTag("pacdot");
void OnTriggerEnter2D(Collider2D collision)
{
// pacman collided with a dot
if (collision.name == "PacMan")
{
Destroy(gameObject);
GameObject.Find("Canvas/Score").GetComponent<Score>().ScoreChange(1);
if (pacdots.length == 0)
{
// All dots hit do something
}
}
}
I'm looking for a way to do something like this:
Gradius
In this game, orbs are following the player. How to do this in Unity where my orbs are following my Player.
Thanks!
A simple solution that i have thought is, lets say i have a player and it is holding it's previous position at start and whenever it moves lets say 5 units then we say to the object that will follow it to follow it's previous position and then we update player's previous position to it's current position and we follow same steps.
I have created a simple test scene and followed these steps :
I have created 2 game objects called Player and FollowPlayer
I have wrote the script below and attached it to the Player
public static event Action<Vector3> FollowMe;
[SerializeField] private float _followDistance;
private Vector3 _previousPosition;
private void Start()
{
_previousPosition = transform.position;
}
private void Update()
{
if(Vector3.Distance(transform.position,_previousPosition) > _followDistance)
{
if(FollowMe != null)
{
FollowMe.Invoke(_previousPosition);
}
_previousPosition = transform.position;
}
}
Then for the FollowPlayer object i have wrote the script below and attached to it
private void Start()
{
Player.FollowMe += OnFollowMe;
}
private void OnDestroy()
{
Player.FollowMe -= OnFollowMe;
}
private void OnFollowMe(Vector3 position)
{
transform.position = position;
}
Again, this is a simple follow script same logic in the Gladius game and i am sure you can use this idea and make it more generic and usable.
In World Scale AR, I want to move to an object I placed using SpawnOnMap. When I touch that object, I want that object to be erased. I made the Player have a script called PlayerController. I made a tag for the object so that when it touches, it should destroy or set it active. When I walk towards the object, nothing happens. I've tried OnTriggerEnter and OnCollisionEnter already. Is there some kind of method I'm missing that Mapbox provides?
public class PelletCollector : MonoBehaviour
{
public int count = 0;
// Start is called before the first frame update
void Start()
{
}
private void OnCollisionEnter(Collision other)
{
if (other.gameObject.tag == "Pellet")
{
count++;
Debug.Log("Collected Pellets: " + count);
other.gameObject.SetActive(false);
//Destroy(other.gameObject);
}
}
}
I have two spawn spots where a player will show up upon connection.
I need that, when one of the players connects on one of the spots, any other player will always spawn at the other spot.
Here's some visual in case it helps: https://goo.gl/Y0ohZC
Thanks in advance,
IC
You can add those two possible spawn spots as empty game objects.
Then I'd make a boolean array and set its states to true or false depending on if the spot is occupied. The spots aren't directly stored in this array so you should make another array.
In C# this would approximately look like this:
public GameObject[] Spots = new GameObject[2]; //Drag the spots in here (In the editor)
bool[] OccupiedSpawnSpots = new bool[2];
int mySpotNumber = -1;
void Start() {
PhotonNetwork.ConnectUsingSettings ("v1.0.0");
}
void OnGUI() {
GUILayout.Label (PhotonNetwork.connectionStateDetailed.ToString ());
}
void OnJoinedLobby()
{
Debug.Log ("Joined the lobby");
PhotonNetwork.JoinRandomRoom ();
}
void OnPhotonRandomJoinFailed()
{
Debug.Log ("No room found. Creating a new one...");
PhotonNetwork.CreateRoom (null);
}
void OnPhotonPlayerConnected(PhotonPlayer player)
{
//If we are the MasterClient, send the list to the connected player
if (PhotonNetwork.isMasterClient)
GetComponent<PhotonView>().RPC("RPC_SendList", player, OccupiedSpawnSpots);
}
void OnApplicationQuit()
{
//If I am outside and others want to connect, my spot shouldn't be still set as occupied:
//I mean if the application quits I'm of course going to be disconnected.
//You have to do this in every possibility of getting disconnected or leaving the room
OccupiedSpawnSpots[mySpotNumber] = false;
//Send the changed List to the others
GetComponent<PhotonView>().RPC("RPC_UpdateList", PhotonTargets.All, OccupiedSpawnSpots);
}
[RPC]
void RPC_SendList(bool[] ListOfMasterClient)
{
OccupiedSpawnSpots = ListOfMasterClient;
//Get the free one
if (OccupiedSpawnSpots[0] == false)
{
//Spawn your player at 0
SpawnMyPlayer(0);
//Set it to occupied
OccupiedSpawnSpots[0] = true;
}
else //so the other must be free
{
//Spawn your player at 1
SpawnMyPlayer(1);
//Set it to occupied
OccupiedSpawnSpots[1] = true;
}
//Send the changed List to the others
GetComponent<PhotonView>().RPC("RPC_UpdateList", PhotonTargets.All, OccupiedSpawnSpots);
}
[RPC]
void RPC_UpdateList(bool[] RecentList)
{
OccupiedSpawnSpots = RecentList;
}
void SpawnMyPlayer(int SpotNumber) {
// Check if spawnspots are set OK
if (Spots == null) {
Debug.LogError ("SpawnSpots aren't assigned!");
return;
}
mySpotNumber = SpotNumber;
// The player object for the network
GameObject myPlayerGO = (GameObject)PhotonNetwork.Instantiate ("PlayerController",
Spots[SpotNumber].transform.position,
Spots[SpotNumber].transform.rotation, 0);
// Enable a disabled script for *this player only, or all would have the same camera, movement, etc
//((MonoBehaviour)myPlayerGO.GetComponent("FPSInputController")).enabled = true;
// Set a camera just for this player
//myPlayerGO.transform.FindChild ("Main Camera").gameObject.SetActive (true);
//standbyCamera.SetActive(false);
}
Note: If you have more than two players, it gets a lot more difficult. This code isn't optimized so maybe you'll find a better one, but it should give you the right idea.
Please ask if anything isn't clear to you...