I want that whenever my player passes through a particular portion of my obstacle it should add 2 points to the score. In order to do this I've made a child of the obstacle. This child contains the box collider which covers that particular portion of the obstacle (I've switched on the Is Trigger in Unity).
Code on child having trigger -
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Score : MonoBehaviour
{
float points;
void Start()
{
}
void Update()
{
Debug.Log(points);
}
void OnTriggerExit2D(Collider2D other)
{
points += 2f;
}
}
The problem is that in the console the points are showing 0s and 2s only like this -
Console
While it should be 0, 2, 4, 6... after passing the obstacle.
Also clones of the original obstacle are being created, i.e. I pass through a new clone each time; in case this is causing the problem.
Yeah it is obvious that it will print out 0s and 2s because your script doesn't use a centralized scoring system it just updates the score in that particular instance. You can make another script call it GameManager where you can make a player score variable and on trigger exit function of your child function would increment the score of that GameManager variable playerscore.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour
{
public float playerPoints = 0f;
}
In Score Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Score : MonoBehaviour
{
public GameManager manager; // Drag and drop the gamemanager object from scene in to this field
void OnTriggerExit2D(Collider2D other)
{
manager.playerPoints += 2f;
Debug.Log(manager.playerPoints);
}
}
Related
I am looking to make my first actual game called Bottomless. It seems I am having a problem with the obstacle generator script in Unity2D. I want the obstacle to generate vertically, where a player is falling down the level.
Here my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Generator : MonoBehaviour
{
public GameObject spike;
public float maxspeed;
public float minspeed;
public float currentspeed;
void Awake()
{
currentspeed = Random.Range(maxspeed, minspeed);
spikegen();
}
void spikegen()
{
GameObject SpikeIns = Instantiate(spike, transform.position, transform.rotation);
}
void Update()
{
}
}
Seems like running this code crashes unity quickly. Does anyone have better alternative?
So, I have been considering your problem, and I think the best thing to do would be to create spawn points in your map pieces for the spikes to fit in. Then, when your player is falling, and the new map is loaded, grab the spawn points, add them to a list, choose one randomly, and then instantiate your spike there. Or get the map pieces themselves to spawn the spikes as they are loaded.
Method 1:
Create spawn points on your map piece. Create and add the following script. Place the spawn points in the list in inspector. And call function on Awake/Start.
using System.Collections;
using UnityEngine;
public class MapScript : MonoBehaviour
{
//Spike you want to instantiate
public GameObject spike;
//List for you to place spawn points in the inspector
public List<GameObject> Spawnpoints = new List<GameObject>();
public void Awake()
{
//Get a random number from 0 to our lists count
int random = Random.Range(0, Spawnpoints.Count);
//Instantiate at the random spawn point
GameObject SpikeIns = Instantiate(spike, Spawnpoints[random].transform.position, transform.rotation);
}
}
Method 2:
Similar to the example above, except the code to spawn happens in the Generator script (this is not the preferred method as we will have to access the map piece's script).
So use the code above but remove the Awake and spike GameObject, and then for your generator script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Generator : MonoBehaviour
{
public GameObject spike;
public float maxspeed;
public float minspeed;
public float currentspeed;
void Awake()
{
currentspeed = Random.Range(maxspeed, minspeed);
spikegen();
}
void Update()
{
}
void spikegen()
{
List<GameObject> Spawners = new List<GameObject>();
foreach(GameObject spawn in refernceToOtherScripts.Spawnpoints)
{
Spawners.Add(spawn);
}
int random = Random.Range(0, Spawners.Count);
GameObject SpikeIns = Instantiate(spike, Spawners[random].transform.position, transform.rotation);
}
}
Neither of these have been tested as I am on my work computer, but they should both work perfectly fine. As you have probably guessed, there are a lot of different way to go about this.
i'm creating a sort of Five Nights at Freddy's game in Unity, using c# code. My idea was to make the animatronic jumpscare the player, and then wait for like 3 seconds and at the end make the player go back to the main menu. How can i make the game (or the code) wait for that 3 seconds before going to the menu?
Thank you
have a look at this example from the official documentation
https://docs.unity3d.com/ScriptReference/MonoBehaviour.Invoke.html
using UnityEngine;
using System.Collections.Generic;
public class ExampleScript : MonoBehaviour
{
// Launches a projectile in 2 seconds
Rigidbody projectile;
void Start()
{
Invoke("LaunchProjectile", 2.0f);
}
void LaunchProjectile()
{
Rigidbody instance = Instantiate(projectile);
instance.velocity = Random.insideUnitSphere * 5.0f;
}
}
So you can add a Restart method to your class and invoke it with 3 seconds of delay in your jumpscare function
void JumpScare()
{
Invoke("Restart", 3.0f);
}
void Restart()
{
// don't forget using UnityEngine.SceneManagement; at top of your file
SceneManager.LoadScene(0); // index of your scene in builds settings
}
You can use async await on the function you use to take the player to the main menu. You need to add the namespace "using System.Threading.Tasks". Here is an example code
using UnityEngine;
using System.Threading.Tasks;
public class Play_audio : MonoBehaviour
{
async void Start()
{
await Task.Delay(1000)
Your_fncton();
}
}
Source: https://vionixstudio.com/2021/11/01/unity-async-await/
I feel like this is a poor question to ask, but I couldn't figure out what the issue was.
I was making a ScoreController and I wanted to make it so that a coin object, when hit, would add 100 to the score GUI. All the coins have this script inside of them:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CoinScoreController : MonoBehaviour
{
public void OnTriggerEnter2D(Collider2D collider)
{
transform.parent.parent.parent.Find("Canvas/ScoreUIController").CollectCoin();
}
}
I can recognize that this is a very poor way of getting an object but I can't figure out what the issue is. Here is the script that I was trying to reference:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ScoreController : MonoBehaviour
{
public static int score = 0; //Number of coins
public static GameObject scoreUI; //A gameObject for the CoinUI
// Update is called once per frame
void Start()
{
scoreUI = GameObject.Find("ScoreUI"); //Automatically sets all coins to have their coinUI GameObject equal the CoinUI UI.
}
public void CollectCoin() //Runs when a coin is collected. Makes it disapear and adds one to the counter.
{
gameObject.SetActive(false);
score += 100;
scoreUI.GetComponent<Text>().text = "Score: " + score.ToString();
}
public void KilledMonster()
{
score += 1000;
}
}
The ScoreControllerUI is inside Canvas so I don't think I have the wrong path. Can you not transform.Find() from the scene? Here is my scene:
As I am sure you can tell, I am new to this site and to Unity, so I apologize for any mistakes in the way I asked this question. Feel free to give me constructive criticism on that as well. I am using unity version 2020.3.24f1 and coding in C#. I don't know if this is relevant but I am coding using visual studio.
Sorry again for any dumb mistakes I made.
Instead of using
transform.parent.parent.parent.Find("Canvas/ScoreUIController").CollectCoin();
use
GameObject.Find("Canvas/ScoreUIController").GetComponent<ScoreController>().CollectCoin();
Suggestion: Define a public ScoreController ScoreUIController in your CoinScoreController (I'm assuming your coin is a prefab) then drag and drop the ScoreUIController into it to assign your script to our defined variable.
Now, you would be able to call
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CoinScoreController : MonoBehaviour
{
public ScoreController ScoreUIController;
public void OnTriggerEnter2D(Collider2D collider)
{
ScoreUIController.CollectCoin();
}
}
P.S. : Please follow tutorials and read documentation first, as I can see your code is very process heavy.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class tankGunLook : MonoBehaviour
{
public GameObject Vehicle;
private Vector3 target = new Vector3(Vehicle.transform.x, 0, Vehicle.transform.z);
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Vehicle != null)
{
transform.LookAt(target);
}
}
}
ERROR: Assets\Scripts\tankGunLook.cs(9,66): error CS0236: A field initializer cannot reference the non-static field, method, or property 'tankGunLook.Vehicle'
I don't quite understand what is not working here, I want the Tank Gun to look at the player or vehicle and but I don't want it to move on the y-axis. So I used 'Vehicle.transform.x' to get the x position but I guess it isn't actually getting it?
Then I want to get the y-position of the Tank Gun itself so it stays stationary but when I do this
ERROR: Assets\Scripts\tankGunLook.cs(9,45): error CS0027: Keyword 'this' is not available in the current context
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class tankGunLook : MonoBehaviour
{
public GameObject Vehicle;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Vector3 target = new Vector3(Vehicle.transform.position.x, transform.position.y, Vehicle.transform.position.z);
transform.LookAt(target);
}
}
I fixed it. I'm not sure how but I assume it's something regarding the fact that the x, y and z positions are constantly updating so they need to be put in the updating section.
I have a script here called EnemyHealth and a script called DatabaseManager. in the DatabaseManager script I am trying to reference a newly created public int deathCount variable from the EnenmyHealth script, but that public variable isn't showing for me while all others are, here is the code
EnemyHealth
using UnityEngine;
namespace CompleteProject
{
public class EnemyHealth : MonoBehaviour
{
public int startingHealth = 100; // The amount of health the enemy starts the game with.
public bool isDead; // Whether the enemy is dead.
public int deathCount;
public int currentHealth; // The current health the enemy has.
public float sinkSpeed = 2.5f; // The speed at which the enemy sinks through the floor when dead.
public int scoreValue = 10; // The amount added to the player's score when the enemy dies.
public AudioClip deathClip; // The sound to play when the enemy dies.
DatabaseManager
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
public class DatabaseManager: MonoBehaviour
{
private void Awake()
{
int x = GameObject.Find("ZomBear").GetComponent<EnemyHealth>().deathCount;
}
it just doesn't seem to find this one variable whilst all the other public ones are visible
The class EnemyHealth is inside the CompleteProject namespace: you should add
using CompleteProject
at the top of DatabaseManager script, in order to have visibility of that namespace.
In your IDE hit save all. ensure that when you edit multiple scripts, you save the nw version of all scripts involved. sounds simple, but i have done this hundreds of times, and it usually only takes a sec to realize it.