I have two c# scripts.
One for the cannon:
using UnityEngine;
using System.Collections;
public class CannonScript : MonoBehaviour {
public GameObject bullet; //bullet object
public Transform spawnpoint; //spawn point
float bulletspeed=-3000f; //bullet speed
public int bullets=10; //number of bullets
void Update () {
if ((Input.GetKeyDown ("space") || Input.GetMouseButtonDown(0)) && bullets > 0) {
GameObject newbullet; //make a new bullet
newbullet=Instantiate(bullet,spawnpoint.position, spawnpoint.rotation)as GameObject; //instantiate the new bullet
newbullet.rigidbody.AddForce(spawnpoint.forward * bulletspeed); //add force to the new bullet
bullets--; //decrease the number of bullets left
}
}
}
Another for the UI text on the screen:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class BulletCountScript : CannonScript { //inherit from the CannonScript
Text text;
void Start () {
text = GetComponent<Text> ();
}
void Update () {
text.text = bullets.ToString(); //display the number of bullets
}
}
When I run it, the UI text on the screen never changes.
I know the CannonScript is working properly, because I can only shoot 10 bullets.
How can I make my UI text display the amount of bullets left?
Am I doing something wrong with inheritance?
I think you are missunderstanding the inheritance concept. The problem I see is both classes are different instances, so that is the reason because the text is always the same.
To achieve what you want, just do something like this:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class BulletCountScript : MonoBehaviour {
public CannonScript cannon;
Text text;
void Start () {
text = GetComponent<Text> ();
}
void Update () {
text.text = cannon.bullets.ToString(); //display the number of bullets
}
}
Just drag the object who owns the CannonScript to the game object attribute
at the BulletCountScript, now, both of them are referencing the same instance.
I hope this helps! Good luck!
Related
I am trying to teleport the character when they touch a cube, but for some reason, it prints the message that it the collision is being detected, but the character's position is not changing. It works for another scenario that is almost exactly the same, but even if I put this in another script, it does not teleport the character. Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class othercollision : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
void OnControllerColliderHit(ControllerColliderHit hit)
{
if (hit.gameObject.name == "teleportcube")
{
gameObject.transform.position = new Vector3(-3184.53f, 20.35f, -171.585f);
Debug.Log("Collision detected");
}
}
}
Here is the script that has something similar working:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
public class detectcollision : MonoBehaviour
{
public GameObject tplocation1;
public GameObject player;
public GameObject entranceloc;
void OnControllerColliderHit(ControllerColliderHit hit)
{
//This if statement does Debug.Log the message and it also changes the player's position.
if (hit.gameObject.name == "trigger")
{
Debug.Log("triggered");
gameObject.transform.position = tplocation1.transform.position;
Thread.Sleep(7);
Application.Quit();
}
//This if statement does not change the player's position, but Debug.Logs the teleporting message.
if (hit.gameObject.name == "entrance")
{
gameObject.transform.position = new Vector3(-3184.53f, 20.35f, -171.585f);
Debug.Log("teleporting...");
}
}
}
Try to make the Vector3 beforehand as a variable or a temporary variable and then assign it to the position. If you did then maybe the values that you have entered are out of boundary somewhy, but that's unlikely, try changing them.
I'm trying to do a 2D platformer with a deaths counter, but I'm facing a problem.
Here is the script I attached to a 3D Text:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DeathCounter : Respawn
{
public Text DeathCount;
public void SetText(int text)
{
string deathsS = deaths.ToString();
DeathCount.text = deathsS;
}
}
And it does nothing.
I'm asking for help please.
What do I do ?
Here is the "Respawn" script, if needed:
using System.Collections;
using UnityEngine.SceneManagement;
using System.Collections.Generic;
using UnityEngine;
public class Respawn : MonoBehaviour
{
public int deaths;
private Scene scene;
void Start()
{
scene = SceneManager.GetActiveScene();
}
void OnCollisionEnter2D(Collision2D col)
{
if(col.transform.CompareTag("Player"))
{
deaths = deaths + 1;
Debug.Log("You are dead");
System.Threading.Thread.Sleep(500);
SceneManager.LoadScene(0);
}
}
}
Thanks a lot for your help !
Have a nice day.
First thing I would do is remove the inheriting of Respawn from your DeathCounter class since it's not extending the functionality of Respawn. I would then set the function to use the passed in parameter to set the text value instead.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DeathCounter : MonoBehaviour
{
public Text DeathCount;
public void SetText(String text)
{
DeathCount.text = "Death Count: " + text;
}
}
Then, in your other class when doing your collision check you can pass the death count value as what to set your DeathCount text to.
using System.Collections;
using UnityEngine.SceneManagement;
using System.Collections.Generic;
using UnityEngine;
public class Respawn : MonoBehaviour
{
public int deaths;
//Reference to your DeathCounter script
public DeathCounter dCounter;
private Scene scene;
void Start()
{
scene = SceneManager.GetActiveScene();
}
void OnCollisionEnter2D(Collision2D col)
{
if(col.transform.CompareTag("Player"))
{
deaths = deaths + 1;
//New line here, with passed in script for updating as a reference
dCounter.SetText(deaths.ToString());
Debug.Log("You are dead");
System.Threading.Thread.Sleep(500);
SceneManager.LoadScene(0);
}
}
}
Edit: One script version...
using System.Collections;
using UnityEngine.SceneManagement;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Respawn : MonoBehaviour
{
public int deaths;
//Reference to your Text, dragged in via the inspector
public Text deathCount;
private Scene scene;
void Start()
{
scene = SceneManager.GetActiveScene();
}
void OnCollisionEnter2D(Collision2D col)
{
if(col.transform.CompareTag("Player"))
{
deaths = deaths + 1;
//Just update the referenced UI text
deathCount.text = "Death Count: " + deaths;
Debug.Log("You are dead");
System.Threading.Thread.Sleep(500);
SceneManager.LoadScene(0);
}
}
}
The problem
basically lies in the LoadScene:
You increase the deaths value BUT then you reload the scene → you also reload the Respawn instance and therefore deaths again will have its original value so probably 0.
You didn't even call the SetText method but even if you would when the scene is reloaded also the Text component is reloaded and will have the original text like of you hadn't called the SetText method at all.
Solution
I'm order to fix it in this case I would use
public class Respawn : MonoBehaviour
{
public static int deaths{ get; private set; }
...
if the value is static it is not bound to a certain instance of Respawn but "lives" directly in the type Respawn. Therefore it keeps its current value also when reloading the scene. The {get; private set;} turns it from a field into a property which can be read by every other class but written only by the Respawn class.
Further you never want to use something like
System.Threading.Thread.Sleep(500);
in the Unity main thread. This completely freezes the main thread and if you e.g. later add any animations etc the app will simply freeze completely. Instead use a Coroutine like
void OnCollisionEnter2D(Collision2D col)
{
if(!col.transform.CompareTag("Player")) return;
deaths += 1;
Debug.Log("You are dead");
StartCoroutine(Reload());
}
private IEnumerator Reload()
{
yield return new WaitForSeconds(0.5f);
SceneManager.LoadScene(0);
}
Finally you have to set the Text after loading the scene so it gets updated also in the reloaded scene.
public class DeathCounter : Respawn
{
public Text DeathCount;
// automatically called when scene is reloaded
private void OnEnable()
{
DeathCount.text = deaths.ToString();
}
}
Sidenote:
In Respawn you store a
scene = SceneManager.GetActiveScene();
but later never use it but instead anyway use
SceneManager.LoadScene(0);
so I would get rid of that Start method .. it only causes unnecessary overhead.
I am a bit confused as to why this is, so basically Im trying to get it to where the camera follows the player without moving left and right with him.
using System.Collections;
using UnityEngine;
public class CameraMotor : MonoBehaviour {
private Transform lookAt;
private Vector3 startOffset;
private Vector3 moveVector;
void Start () {
GameObject.FindGameObjectWithTag ("Player").transform;
}
// Update is called once per frame
void Update () {
moveVector = lookAt.position + startOffset;
//X
moveVector.x = 0; //center of track
//Y[image][1]
moveVector.y = Mathf.Clamp(moveVector.y,3,5);// for ramps/stairs
transform.position = moveVector;
}
}
I think you want GameObject.FindWithTag
https://docs.unity3d.com/ScriptReference/GameObject.FindWithTag.html
Even so,
GameObject.FindWithTag ("Player").transform;
does nothing. (Nothing usefull atleast)
lookAt is never assigned, so im guessing what you want to do is
lookAt = GameObject.FindWithTag ("Player").transform;
If you are looking for an object in your scene, then use this simple script;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AnswerScript : MonoBehaviour {
private Transform lookAt;
// Use this for initialization
void Start () {
lookAt.Find("The Object That You are Looking For");
}
// Update is called once per frame
void Update () {
}
}
I just want to move a bullet (but it doesn't work) and test on cube (but the code too did not move the cube).
The commented codes also did not move the game object.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movetest : MonoBehaviour
{
//public GameObject cube;
// Use this for initialization
public GameObject testmovecube;
public Rigidbody rb;
void Start () {
//testmovecube = this.GetComponent<GameObject>();
//rb = testmovecube.GetComponent<Rigidbody>();
move();
//
}
// Update is called once per frame
void Update () {
}
private void move()
{
testmovecube.transform.position =
Vector3.MoveTowards(transform.position, new Vector3(226, 1, 226) , 2);
//transform.Translate(Vector3.forward);
//rb.AddForce(Vector3.forward);
}
}
Please any help is appreciated.
How do I set gameobject(myCanvas) to be false during the first play?
I've put this script into the cube, and when I click the cube it will show the Canvas.
I haven't been clicking on the cube but, the canvas has already come out.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class MouseDownText : MonoBehaviour {
public Canvas myCanvas;
void Start()
{
// first start game. gameobject will turn off
myCanvas.gameObject.SetActive(false);
}
void OnMouseDown()
{
// for switch on/off
myCanvas.gameObject.SetActive(!myCanvas.gameObject.activeSelf);
}
}
From what I understand you have a canvas component attached to a game object (a cube) and you want to use mouse clicks to toggle whether or not the canvas is active.
Have you tried:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class MouseDownText : MonoBehaviour {
public Canvas myCanvas;
// Use this for initialization
void Start () {
myCanvas = GetComponent<Canvas> ();
myCanvas.enabled = false;
}
// Update is called once per frame
void Update () {
}
void OnMouseDown()
{
// for switch on/off
if (myCanvas.enabled)
myCanvas.enabled = false;
else
myCanvas.enabled = true;
}
}
Also make sure you haven't accidentally enabled it in some other code somewhere.