I'm trying to make a grenade throwing script but when i test it, it always spawn 2 grenade at the same time.
public class GrenadeThrow : MonoBehaviour {
public GameObject bulletprefab;
float speed =20f;
// Use this for initialization
void Start () { }
// Update is called once per frame
void Update () {
if (Input.GetButtonUp("Fire1"))
{
Camera cam = Camera.main;
GameObject Grenade = Instantiate(bulletprefab, cam.transform.position + cam.transform.forward, cam.transform.rotation);
Grenade.GetComponent<Rigidbody>().AddForce(cam.transform.forward * speed, ForceMode.Impulse);
}
}
}
First of all, Input.GetButtonDown is more appropriate for this than Input.GetButtonUp. You can try it and see if Input.GetButtonDown is still what you want.
when i test it, it always spawn 2 grenade at the same time
Assuming that this is the actual code you are using to spawn and throw Objects, then it should work fine.
There two likely problems:
1.The GrenadeThrow script is likely attached to the-same GameObject multiple times.
2.The problem is likely to be that you have your GrenadeThrow script attached to multiple GameObjects. It should only be attached to one GameObject.
Related
I'm making a game on unity where the user selects a character and the character spawns into the game world. The world consists of different doors. I want to add a transition animation (just a regular fade) between scenes in the game world but because the character is instantiated during runtime, I'm not sure how to attach the animator to the character. I also want the animation to trigger upon collision of the player with a door. I know how to create the animation clips and the animator but I need help on knowing when and how to attach the animator to an object that's going to be instantiated during runtime.
Will I attach the animator in OnCollisionEnter() function? If so, how do I reference that animator through code?
Here is my code for OnCollisionEnter in a script that is attached to the player during runtime. (this works fine)
private void OnCollisionEnter(Collision collision)
{
GameObject door = collision.gameObject;
if (door.CompareTag("ExitDoor"))
SceneManager.LoadScene(0); // spawn back at main lobby
else if (door.CompareTag("RoomDoor"))
{
GameObject Room = door.transform.parent.gameObject;
if (Room.name.Equals("Room1Door"))
SceneManager.LoadScene(1); // go to first room
if (Room.name.Equals("Room2Door"))
SceneManager.LoadScene(2); // go to second room
if (Room.name.Equals("Room3Door"))
SceneManager.LoadScene(3); // go to third room
}
}
And here is the script of instantiating the player during runtime when the scene is loaded (this is in another script)
public GameObject InstantiatePlayer()
{
characterIndex = PlayerPrefs.GetInt(playerprefkey);
selectedChar = characters[characterIndex];
selectedChar.tag = "Player";
selectedChar.AddComponent<MoveRooms>(); //attaches the script where OnCollisionEnter is
return Instantiate(selectedChar, spawnPoint.transform.position, spawnPoint.transform.rotation);
}
to get the Animator , you can do this if the script is attached
Animator anim;
void Start()
{
anim = gameObject.GetComponent<Animator>();
}
else if it is not attached you can try something like this
GameObject object;
Animator anim;
void Start()
{
object = GameObject.Find("objectsname");
anim = object.GetComponent<Animator>();
}
For further details how to use Animator
https://docs.unity3d.com/ScriptReference/Animator.html
https://docs.unity3d.com/ScriptReference/Animator.Play.html
https://docs.unity3d.com/ScriptReference/Animator.SetTrigger.html
As for a transition, you can try to use Caroutines. What Caroutines are is it executes a piece of code 'on the side' whie the other codes continue. It can be used to "wait" for a few seconds (or more). Its very useful and you can do alot with it.
some examplee
public class ExampleClass : MonoBehaviour
{
void Start()
{
// Start function as a coroutine.
StartCoroutine(waitForSeconds);
}
private IEnumerator waitForSeconds()
{
//do something
yield return new WaitForSeconds(1f); // the number is in seconds.
//do something else
}
}
https://docs.unity3d.com/ScriptReference/Coroutine.html
Below is my code but I don't know why when the _lazerPrefab spawns it doesn't move, even though _lazerSpeed != 0. I dont't know where the problem is.
if (Input.GetKeyDown(KeyCode.Space))
{
Instantiate(_lazerPrefab, transform.position, Quaternion.identity);
_lazerPrefab.transform.Translate(Vector3.up * _lazerSpeed * Time.deltaTime);
}
You cannot move the prefab itself, as prefabs are like "blueprints" that are used to construct real object instances, hence the name. You can indeed move those instances. Instantiate() will return the reference to the newly created copy/instance!
if (Input.GetKeyDown(KeyCode.Space))
{
GameObject new_lazer = Instantiate(_lazerPrefab, transform.position, Quaternion.identity);
new_lazer.transform.Translate(Vector3.up * _lazerSpeed * Time.deltaTime);
}
But this code will always spawn a new instance when you press Space. And once you spawned a 2nd, you will no longer move the first as the Translate call for the first instance is not done anymore.
So you need to adapt your logic. Either put a "move/accelerate forward" script on the lazers, or keep the references returned from Instantiate() in a list and maintain them and their lifetime. Another way could be adding a RigidBody and giving it a velocity so it keeps moving on it's own. Impact can be handled with a collider and the OnCollisionEnter or OnTriggerEnter (if the collider is marked as trigger) functions, where you can trigger sounds, damage etc.
You are only moving the _lazerprefab when Input.GetKeyDown(KeyCode.Space) is true.
If you want to move the gameObject more than once after you press space you would need to add the move code into the gameObjects Update() Method itself.
You would need to attach this script to the _lazerprefab GameObject.
Example Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveObstacles : MonoBehaviour {
[SerializeField]
private float _lazerSpeed = 10f;
private void FixedUpdate() {
gameObject.transform.Translate(Vector3.up * _lazerSpeed * Time.deltaTime);
}
}
We are now able to just call the Instantiate() Function and the instantiated GameObject will move automatically each frame.
Example Move Call:
if (Input.GetKeyDown(KeyCode.Space)) {
Instantiate(_lazerPrefab, transform.position, Quaternion.identity);
}
In my platform game I have just added some checkpoints, so that if the player dies doesn't necessarily spawn at the beginning of the track.
ghfdghdggfhfg
using UnityEngine;
public class CheckPoints : MonoBehaviour
{
[SerializeField] private Grounded game;
void Update()
{
transform.Rotate(0, 0, 5);
}
private void OnTriggerEnter() {
game.updatedCheckPointPosition = transform.position;
Destroy(this);
}
}
What I unsuccessfully tried to do is to set the public float variable of the Grounded script to the current position of the CheckPoint itself, which should be destroyed after doing that.
Any information or help on how to do this is really appreciated.
From Destroy
The object obj will be destroyed now or if a time is specified t seconds from now.
If obj is a Component it will remove the component from the GameObject and destroy it. [But keep the rest of the GameObject intact!]
If obj is a GameObject it will destroy the GameObject, all its components and all transform children of the GameObject.
this refers to the according component instance. What you want is rather
Destroy(gameObject);
OnTriggerEnter requires a parameter of type Collider in order to work
private void OnTriggerEnter(Collider other)
{
game.updatedCheckPointPosition = transform.position;
Destroy(this);
}
Note however that this way round the player has to be a trigger while the checkpoint a non-trigger! I would actually rather do it the other way round and make the chackpoint a trigger and rather let the player object check for OnTriggerEnter.
This is semi complicated of a question but I'll do my best to explain it:
I am making this mobile game in which you have to shoot four cubes. I'm trying to make it so when the cubes are shot by a bullet, they're destroyed and a UI text says 1/4, to 4/4 whenever a cube is shot. But it's being really weird and only counts to 1/4 even when all four cubes are shot and destroyed. I put these two scripts on the bullets (I made two separate scripts to see if that would do anything, it didn't)
And to give a better idea of what I'm talking about, here's a screenshot of the game itself.
I've been using Unity for about 6 days, so I apologize for anything I say that's noob-ish.
EDIT
So I combined the two scripts onto an empty gameobject and here's the new script:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class GameManagerScript : MonoBehaviour {
public GameObject cubes;
public Text countText;
public int cubeCount;
public Transform target;
// Use this for initialization
void Start () {
}
void OnTriggerEnter(Collider other)
{
cubes = other.gameObject;
}
// Update is called once per frame
void Update () {
cubes.transform.position = Vector3.MoveTowards(transform.position, target.position, 1f * Time.deltaTime);
if (cubes.gameObject.tag == "BULLET")
{
cubeCount = cubeCount + 1;
countText.text = cubeCount + "/4";
cubes.SetActive(false);
}
}
}
ANOTHER EDIT
I tried everything, so is there a way to detect when all the children in a parent on the Hierarchy are destroyed? Instead of counting up? This can give a better idea:
So I want to be able to detect when Cube, Cube1, Cube2, and Cube3 have all been destroyed.
The answer is pretty simple: Since every individual bullet has that script, each bullet has its own score.
For something like a score you want a single spot to store it, e.g. a script on an empty gameobject that serves as game controller. Just access that in the collision and increase the score (maybe have a look on singletons here).
You can combine those two scripts and actually it might be better to not have this on the bullet, but on the target because there are probably less of them which will save you some performance. (And it does more sense from a logical point of view.)
Edit:
I assume you create the bullets using Instantiate with a prefab. A prefab (= blueprint) is not actually in the game (only objects that are in the scene/hierarchy are in the game). Every use of Instantiate will create a new instance of that prefab with it's own version of components. A singleton is a thing that can only exist once, but also and that is why I mention it here, you can access it without something like Find. It is some sort of static. And an empty gameobject is just an object without visuals. You can easily create one in unity (rightclick > create empty). They are typically used as container and scriptholders.
Edit:
What you want is:
An empty gameobject with a script which holds the score.
A script that detects the collision using OnTriggerEnter and this script will either be on the bullets or on the targets.
Now, this is just a very quick example and can be optimized, but I hope this will give you an idea.
The script for the score, to be placed on an empty gameobject:
public class ScoreManager : MonoBehaviour
{
public Text scoreText; // the text object that displays the score, populate e.g. via inspector
private int score;
public void IncrementScore()
{
score++;
scoreText.text = score.ToString();
}
}
The collision script as bullet version:
public class Bullet : MonoBehaviour
{
private ScoreManager scoreManager;
private void Start()
{
scoreManager = GameObject.FindWithTag("GameManager").GetComponent<ScoreManager>(); // give the score manager empty gameobject that tag
}
private void OnTriggerEnter(Collider other)
{
if(other.CompareTag("Target") == true)
{
// update score
scoreManager.IncrementScore();
// handle target, in this example it's just destroyed
Destroy(other.gameObject);
}
}
}
I actually have 2 issues. The first problem I have is that when I start my game all 4 cannons do their animation sequence for no reason, nothing happens. I'd like this to not happen. The second problem I have is the cannon ball that shoots out spawns on the floor and flies along the floor. Here is the code for the firing sequence:
using UnityEngine;
using System.Collections;
public class Cannon : MonoBehaviour {
public AudioClip sound;
public GameObject prefab;
public GameObject ejectPoint;
void Start () {
prefab = Resources.Load ("Cannon_Ball") as GameObject;
}
public void Fire () {
GameObject Cannon_Ball = Instantiate (prefab) as GameObject;
Cannon_Ball.transform.position = transform.position + ejectPoint.transform.forward * 2;
Rigidbody rd = Cannon_Ball.GetComponent<Rigidbody> ();
rd.velocity = ejectPoint.transform.forward * 130;
AudioSource.PlayClipAtPoint(sound, transform.position, 1);
GetComponent<Animation> ().Play ();
}
}
Here is a GIF of the problem:
fix 1: Uncheck 'Play Automatically' or find equal option in your Animator. I think after you start game, your Animator change his state from "Start" to "Shoot" because of bad conditions setting or even totally lake of conditions . If you paste here screenshot of your animator, that would be useful.
If you want to fix your second problem you should watch this video:
BRICK SHOOTER - Official Unity Tutorial