First of all I apologize that this texts looks so weird.
It's my first time to use stackoverflow
I start to learn about Unity and C#.
And today I learn about move cube in unity, gonna review the script and I think i failed.
I put script in cube1 at Hierarchy, click the solution build at C# and run at unity.
And didn't work.
public class TRAIN : MonoBehaviour
{
// return cube1 to cube. cube1 is name of cube object in unity
GameObject cube = GameObject.Find("cube1");
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
//move cube1 to z-axis at speed 1
cube.transform.position += new Vector3(0, 0, 1);
}
}
How can I move cube1?
You can't call GameObject.Find() directly there, you should be getting an error in the console.
UnityException: Find is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead
Do it in the Awake() or Start() instead.
public class TRAIN : MonoBehaviour
{
GameObject cube;
void Start()
{
cube = GameObject.Find("cube1");
}
Related
So i am really, really new to Unity and C# and i just want to try a few things like a shooting script. The way i want it to work is that i have a game object, in my case it's called "Glock" and as a child of that game object i have an empty called "bulletSpawn". I now want to assign a script to "bulletSpawn" that spawns in an predefined object whenever i hit the left mouse button.
What i tried:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class spawnBullet : MonoBehaviour
{
public GameObject bullet;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
GameObject newBullet = Instantiate(bullet, new Vector3(0, 0, 0), Quaternion.identity);
}
}
}
And it kinda works. Whatever, it clones everything in an exponential way, so when i hit the left mouse button it spawns in the object but it also spawns in an object called "Glock(Clone)" and if i hit it again, it spawns: "Glock(Clone)","Glock(Clone)(Clone)","bullet(Clone)" and "bullet(Clone)(Clone)". And that doubles each time i click. My second problem is, that it spawns every object at the global coordinates [0,0,0] and not the local ones of the empty.
As Helmi say are you using a bullet prefab and not the Glock prefab?
This code under should fix your position problem.
if (Input.GetButtonDown("Fire1"))
{
GameObject newBullet = Instantiate(bullet, transform.position, Quaternion.identity);
}
I've searched around and I just can't get this to work. I think I just don't know the proper syntax, or just doesn't quite grasp the context.
I have a BombDrop script that holds a public int. I got this to work with public static, but Someone said that that is a really bad programming habit and that I should learn encapsulation. Here is what I wrote:
BombDrop script:
<!-- language: c# -->
public class BombDrop : MonoBehaviour {
public GameObject BombPrefab;
//Bombs that the player can drop
public int maxBombs = 1;
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.Space)){
if(maxBombs > 0){
DropBomb();
//telling in console current bombs
Debug.Log("maxBombs = " + maxBombs);
}
}
}
void DropBomb(){
// remove one bomb from the current maxBombs
maxBombs -= 1;
// spawn bomb prefab
Vector2 pos = transform.position;
pos.x = Mathf.Round(pos.x);
pos.y = Mathf.Round(pos.y);
Instantiate(BombPrefab, pos, Quaternion.identity);
}
}
So I want the Bomb script that's attached to the prefabgameobject Bombprefab to access the maxBombs integer in BombDrop, so that when the bomb is destroyed it adds + one to maxBombs in BombDrop.
And this is the Bomb script that needs the reference.
public class Bomb : MonoBehaviour {
// Time after which the bomb explodes
float time = 3.0f;
// Explosion Prefab
public GameObject explosion;
BoxCollider2D collider;
private BombDrop BombDropScript;
void Awake (){
BombDropScript = GetComponent<BombDrop> ();
}
void Start () {
collider = gameObject.GetComponent<BoxCollider2D> ();
// Call the Explode function after a few seconds
Invoke("Explode", time);
}
void OnTriggerExit2D(Collider2D other){
collider.isTrigger = false;
}
void Explode() {
// Remove Bomb from game
Destroy(gameObject);
// When bomb is destroyed add 1 to the max
// number of bombs you can drop simultaneously .
BombDropScript.maxBombs += 1;
// Spawn Explosion
Instantiate(explosion,
transform.position,
Quaternion.identity);
In the documentation it says that it should be something like
BombDropScript = otherGameObject.GetComponent<BombDrop>();
But that doesn't work. Maybe I just don't understand the syntax here. Is it suppose to say otherGameObject? Cause that doesn't do anything. I still get the error : "Object reference not set do an instance of an object" on my BombDropScript.maxBombs down in the explode()
You need to find the GameObject that contains the script Component that you plan to get a reference to. Make sure the GameObject is already in the scene, or Find will return null.
GameObject g = GameObject.Find("GameObject Name");
Then you can grab the script:
BombDrop bScript = g.GetComponent<BombDrop>();
Then you can access the variables and functions of the Script.
bScript.foo();
I just realized that I answered a very similar question the other day, check here:
Don't know how to get enemy's health
I'll expand a bit on your question since I already answered it.
What your code is doing is saying "Look within my GameObject for a BombDropScript, most of the time the script won't be attached to the same GameObject.
Also use a setter and getter for maxBombs.
public class BombDrop : MonoBehaviour
{
public void setMaxBombs(int amount)
{
maxBombs += amount;
}
public int getMaxBombs()
{
return maxBombs;
}
}
use it in start instead of awake and dont use Destroy(gameObject); you are destroying your game Object then you want something from it
void Start () {
BombDropScript =gameObject.GetComponent<BombDrop> ();
collider = gameObject.GetComponent<BoxCollider2D> ();
// Call the Explode function after a few seconds
Invoke("Explode", time);
}
void Explode() {
//..
//..
//at last
Destroy(gameObject);
}
if you want to access a script in another gameObject you should assign the game object via inspector and access it like that
public gameObject another;
void Start () {
BombDropScript =another.GetComponent<BombDrop> ();
}
Can Use this :
entBombDropScript.maxBombs += 1;
Before :
Destroy(gameObject);
I just want to say that you can increase the maxBombs value before Destroying the game object. it is necessary because, if you destroy game object first and then increases the value so at that time the reference of your script BombDropScript will be gone and you can not modify the value's in it.
I am coding a tower defense game in Unity, and I've ran into a snag while trying to figure out a way to place towers. My idea is to be able to click an art asset in the game when the player has a certain amount of points, and it replaces that art asset with a tower. Unfortunately, even when the player has the right amount of points, the object does not instantiate. I have made sure to link the prefab to the script, but it doesn't work. I'm stumped, the logic of the code seems right but maybe someone can help me figure out what's wrong here.
public class PointManager : MonoBehaviour
{
public int pointCount;
public Text pointDisplay;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
pointDisplay.text = "Points: " + pointCount;
}
}
public class PlaceTower: MonoBehaviour
{
public GameObject Tower;
private GameObject firstTower;
int placeCost = 25;
private PointManager pointsGained;
// Start is called before the first frame update
void Start()
{
pointsGained = GameObject.FindGameObjectWithTag("Point").GetComponent<PointManager>();
}
// Update is called once per frame
void Update()
{
}
private void OnMouseDown()
{
if (pointsGained.pointCount >= placeCost)
{
firstTower = Instantiate(Tower, transform.position, Quaternion.identity);
//Destroy(this.gameObject);
}
}
}
I got it. The problem was not with my code, but with my prefabs. In the documentation, I misread that OnMouseDown works on objects with colliders. While I had set up a circle collider on the object I was trying to instantiate, I had failed to put one on the object I was trying to instantiate from. Doing so fixed the problem immediately. A simple mistake that I would have completely glanced over had it not been for a second opinion. Thank you, Pac0!
I'm trying to write a spawn controller script. Fundamentally I'm also asking to see if there's a better way to do this?
What:
Every x seconds, SpawnController.cs selects a random unit, start, PitStop and final positions from a series of arrays.
It calls 'SpawnSingle.cs' with these variables.
'SpawnSingle.cs' instantiates the GameObject, sends the destination to 'navMove' script attached to the GameObject once when created, waits for x seconds when it arrives and changes destination.
Question:
How do I make each instance of my called script (SpawnSingle)
'wait' for x seconds midway, as it's controlling the gameObject. I
can't use a coroutine to stop it.
How do I pass in the second set of coordinates after? It doesn't
seem to work when using the SpawnController.
//In SpawnController.cs
...
...
private Transform currentDestination;
private NavMove moveScript;
private GameObject newEnemy;
public static SpawnSingle newSpawn = new SpawnSingle();
void Start()
{
// To build a function to randomise the route and spawn at intervals
spawnCounter = 0;
Spawn();
spawnCounter++;
Spawn();
void Spawn()
{
newSpawn.SpawnEnemy(Enemies[spawnCounter], SpawnPoint[spawnCounter], PitStop[spawnCounter], Destination[spawnCounter]);
}
SpawnSingle.cs then assigns the first stop (pitStop) and tells it to move there using navAgents.
Problem:
When it arrives at PitStop location, I want it to wait for a few seconds, then continue on to the final destination.
This all worked OK for single instances without the Controller.
// in SpawnSingle.cs
private Transform currentDestination;
private NavMove moveScript; // This script moves the navAgent
private GameObject newEnemy;
public void SpawnEnemy(GameObject Enemies, Transform SpawnPoint, Transform PitStop, Transform Destination)
{
newEnemy = GameObject.Instantiate(Enemies, SpawnPoint.position, Quaternion.identity) as GameObject;
moveScript = newEnemy.GetComponent<NavMove>();
currentDestination = PitStop;
moveScript.destination = currentDestination;
if (arrivedAtP())
{
// Stop and wait x seconds
moveScript.nav.enabled = false;
// ***HELP HERE*** How do I make this script wait? Coroutines don't work when this script is called from an extenral source it seems?
// Wait for x seconds--
//Continue moving to final destination
//*** HELP HERE*** When instantiated from an external script, this doesn't continue to pass in the new location?***
moveScript.nav.enabled = true;
currentDestination = Destination;
moveScript.destination = currentDestination;
}
}
I think the best way to go about solving this is to make separate components for each behaviour.
Right now your spawner is responsible for 3 things:
1) making enemies, 2) setting initial nav points, 3) updating nav points later.
I would advise making your spawner only responsible for spawning objects.
Then make a navigator component that creates the nav points and pit stops etc.
so something like this:
public class Spawner : MonoBehaviour {
//only spawns, attached to some gameobject
public GameObject prefabToSpawn;
public GameObject Spawn() {
//instantiate etc..
GameObject newObject = Instantiate(prefabToSpawn);
return newObject
}
}
public class EnemyManager : MonoBehaviour {
//attached to an empty gameObject
public Spawner spawner;
public Enemy CreateNewEnemy () {
GameObject newEnemy = spawner.Spawn ();
// add it to list of enemies or something
//other stuff to do with managing enemies
}
}
public class Navigator : MonoBehaviour {
//Attached to Enemy prefab
Destination currentDestination;
public float changeDestinationTime;
void Start() {
currentDestination = //first place you want to go
InvokeRepeating ("NewDestination", changeDestinationTime, changeDestinationTime);
}
void NewDestination() {
currentDestination = // next place you want to go
}
}
Obviously that's not a complete solution but it should help get you pointed in the right direction (and change directions every 8 secs :D ). Let me know if I misunderstood what you're trying to do!
I'm looking to create a piece of terrain in unity using only a script (c# preferably) to do this rather than the menu options on the editor. So far I only have this code below, but I don't know what to do next to get it to appear on the scene, can anyone help?
Thank you
using UnityEngine;
using System.Collections;
public class terraintest : MonoBehaviour {
// Use this for initialization
void Start () {
GameObject terrain = new GameObject();
TerrainData _terraindata = new TerrainData();
terrain = Terrain.CreateTerrainGameObject(_terraindata);
}
// Update is called once per frame
void Update () {
}
}
Simply adding :
Vector3 position = ... //the ingame position you want your terrain at
GameObject ingameTerrainGameObject = Instantiate(terrain, position, Quaternion.identity);
should make the terrain appear ingame. The Instantiate method returns a reference to the gameobject spawned ingame, so if you later want to access it, you can use that reference.