Unity 3D Instantiated Prefabs stop moving - c#

I set up a pretty simple scene where a prefab is being instantiated every x seconds. I applied a transform.Translate on the instances in the Update() function. Everything works fine until a second object is spawned, the first one stops moving and all the instances stop at my translate value.
Here is my script, attached to an empty GameObject:
using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
public GameObject prefab;
private Transform prefabInstance;
void spawnEnemy() {
GameObject newObject = (GameObject)Instantiate(prefab.gameObject, transform.position, transform.rotation);
prefabInstance = newObject.transform;
}
void Start() {
InvokeRepeating ("spawnEnemy", 1F, 1F);
}
void Update () {
if (prefabInstance) {
prefabInstance.transform.Translate (new Vector3(4,0,0) * Time.deltaTime);
}
}
}

Your movement is occuring on the prefabInstance object in your Update(), however, that object gets overwritten when the second instance is created, so only your last instantiated prefab will move.
You should consider splitting your code into 2 scripts, the first one to spawn the prefab, and the second script actually on the prefab to move it.
public class Test : MonoBehaviour {
public GameObject prefab;
void spawnEnemy() {
Instantiate(prefab, transform.position, transform.rotation);
}
void Start() {
InvokeRepeating ("spawnEnemy", 1F, 1F);
}
}
and put this script on your prefab:
public class Enemy : MonoBehaviour {
void Update () {
transform.Translate (new Vector3(4,0,0) * Time.deltaTime);
}
}

Related

The Object you want to instantiate is null. (Error Unity)

I've tried to fix this problem for many days, looked for every result in a web and didn't get any suitable answers to me...
With this problem I can run my game, but it shows up every time I shoot the bullet prefab.
This is a player shooting script, it shows up a problem when I try to Instatiate(bulletRef);
public GameObject bulletRef;
// Start is called before the first frame update
void Start()
{
bulletRef = Resources.Load("Bullet") as GameObject;
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Z))
{
// By pressing the button we create an instance of a bullet
Instantiate(bulletRef);
bulletRef.transform.position = new Vector3(transform.position.x + .4f, transform.position.y + .2f, -1);
}
}
I think that those codes look suspicious to me, maybe the roots of this problem are coming out from them
here is a script for bullet
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletScript : MonoBehaviour
{
public float speed = 20f;
public int damage = 1;
public Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
rb.velocity = -transform.up * speed;
}
private void OnTriggerEnter2D(Collider2D collider)
{
Destruction enemy = collider.GetComponent<Destruction>();
if (enemy != null)
{
enemy.TakeDamage(damage);
}
Destroy(gameObject);
}
}
This is a script for destroying the bullet. I don't personally think that there is an issue with this code, but it is for you to understand how my bullet dissapears
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Destruction : MonoBehaviour
{
public int health = 1;
public void TakeDamage(int damage)
{
health -= damage;
if (health <= 0)
{
Die();
}
}
void Die()
{
Destroy(this.gameObject);
}
private void OnTriggerEnter2D(Collider2D collision)
{
ScoreManager.instance.AddPoint();
}
}
The problem lies in your Update() method of your first script
Instantiate(bulletRef);
bulletRef.transform.position = new Vector3(transform.position.x + .4f, transform.position.y + .2f, -1);
You are instantiating the gameobject bulletRef but not assigning it to any field. Also, you are changing the position of just a reference to the gameobject you just loaded from the resources. You didn't have a reference to the gameobject in the scene, you have a reference to the gameobject in your resources. To get a reference to the gameobject you just instantiated into your scene, assign the instantiated gameobject to a field. But the function Instantiate returns an Object hence we typecast it to GameObject as
GameObject bulletRefObject = Instantiate(bulletRef) as GameObject;
bulletRefObject.transform.position = new Vector3(transform.position.x + .4f, transform.position.y + .2f, -1);

Is there any way to assign player to Camera after the game started in unity?

Okay, so I create an endless runner game that has character selection. The goal is, when the scene starts (with no player in the hierarchy), the game manager will instantiate the player based on the selected player. But, the CameraController, have the error "Object reference not set to an instance of an object", it cannot find the instantiate player object
Here is how I instantiate my player:
void Start()
{
int selectedCharacter = PlayerPrefs.GetInt("selectedChar");
GameObject prefab = characterPrefabs[selectedCharacter];
GameObject clone = Instantiate(prefab, playerStartPoint, Quaternion.identity);
player = FindObjectOfType<PlayerScript>();
platformStartPoint = platformGenerator.position;
scoreManager = FindObjectOfType<ScoreManager>();
Reset();
}
And this is my camera script:
public class CameraController : MonoBehaviour{
public PlayerScript player;
private Vector3 lastPlayerPosition;
private float distToMove;
// Start is called before the first frame update
void Start()
{
player = FindObjectOfType<PlayerScript>();
lastPlayerPosition = player.transform.position;
}
// Update is called once per frame
void Update()
{
distToMove = player.transform.position.x - lastPlayerPosition.x;
transform.position = new Vector3(transform.position.x + distToMove, transform.position.y, transform.position.z);
lastPlayerPosition = player.transform.position;
}
}
The camera should be move along with the character, do you have any idea how to fix this? Thank you
I'm assuming your Camera tries to search for the player before they get instantiated based on what you mentioned. There are several different approaches to fixing this.
Method 1
Have the script that instantiates the player grab the camera and assign the player instance.
Example
// Call this after instantiating a player instance
FindObjectOfType<CameraController>().AssignTarget(player);
// Add this to CameraController.cs
public void AssignTarget(PlayerScript player)
{
this.player = player;
lastPlayerPosition = player.transform.position;
}
Method 2
Add an event field somewhere that informs when player has been instantiated and subscribe to it using your camera.
Example
using System;
using UnityEngine;
public class PlayerScript : MonoBehaviour
{
public static event Action<PlayerScript> InstanceStarted;
private void Start()
{
InstanceStarted?.Invoke(this);
}
}
using UnityEngine;
public class CameraController : MonoBehaviour
{
private Player player;
private void Start()
{
player = FindObjectOfType<PlayerScript>();
if (player == null)
PlayerScript.InstanceStarted += OnPlayerInstanceStarted;
}
private void OnPlayerInstanceStarted(PlayerScript instance)
{
PlayerScript.InstanceStarted -= OnPlayerInstanceStarted;
player = instance;
}
}
Method 3
Add DefaultExecutionOrder attribute to your scripts and change the execution order to ensure that the player gets instantiated before the Camera starts to look for one.
Example
[DefaultExecutionOrder(100)]
public class TestScript : MonoBehaviour {}
Method 4
Have a Coroutine that periodically checks whether an instance of a player is available before allowing the Camera to do anything.
Example
using System.Collections;
using UnityEngine;
public class CameraController : MonoBehaviour
{
private PlayerScript player;
private void Start()
{
StartCoroutine(StartOncePlayerIsFound());
}
private IEnumerator StartOncePlayerIsFound()
{
player = FindObjectOfType<PlayerScript>();
while (player == null)
{
// Feel free to yield "WaitForEndOfFrame" or "null"
// if you wish to search for player every frame
yield return new WaitForSeconds(0.1f);
player = FindObjectOfType<PlayerScript>();
}
// ...
}
}
Try this one
transform.position = new Vector3(player.transform.position.x, transform.position.y, transform.position.z);

Spawning object and Destroing player character

I writing runner.
I have two problems
I have spawning object (quad).
1) I try to spawn my object many times , but it spawning once.
My Spawn script:
using UnityEngine;
using System.Collections;
public class SpawnScript : MonoBehaviour {
public GameObject[] obj;
public float spawnMin = 1f;
public float spawnMax = 2f;
// Use this for initialization
void Start () {
Spawn();
}
void Spawn()
{
Instantiate(obj[Random.Range(0, obj.GetLength(0))], transform.position, Quaternion.identity);
Invoke("Spawn", Random.Range(spawnMin, spawnMax));
}
}
I try to make spawning script, like here Spawning but facing second problem
And second problem
2) I have destroyer script, I use it on spawning quad. On first object Player character destroys, on second object it through it.
Destroyer script
using UnityEngine;
using System.Collections;
public class DestroyerScript : MonoBehaviour {
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player") {
Destroy(other.gameObject);
Application.LoadLevel(1);
return;
}
For the spawning problem, you can use a coroutine.
void Start()
{
StartCoroutine(Spawn());
}
IEnumerator Spawn()
{
// Instantiate your game objects
Instantiate(obj[Random.Range(0, obj.GetLength(0))], transform.position, Quaternion.identity);
// Wait for a random time interval
yield return new WaitForSeconds(Random.Range(spawnMin, spawnMax));
}
For the collision problem, my guess is, the quad is destroyed by the player in player's collision script.

Making Destroyer (UnityC#)

I making simple runner game.
I want do have some block over which player which jump.
I make a prefab and quad.
Attached Spawn script:
using UnityEngine;
using System.Collections;
public class SpawnScript : MonoBehaviour {
public GameObject[] obj;
public float spawnMin = 1f;
public float spawnMax = 1f;
// Use this for initialization
void Start ()
{
Spawn();
}
void Spawn()
{
Instantiate(obj[Random.Range(0, obj.GetLength(0))], transform.position, Quaternion.identity);
Invoke("Spawn", Random.Range(spawnMin, spawnMax));
}
}
Also I attached Destroyer script:
using UnityEngine;
using System.Collections;
public class DestroyerScript : MonoBehaviour {
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player")
{
Application.LoadLevel(1);
return;
}
if (other.gameObject.transform.parent)
{
Destroy(other.gameObject.transform.parent.gameObject);
}
else
{
Destroy(other.gameObject);
}
}
}
But when player enter this object nothing happens.
Screen of my Quad:
Where is my mistake?
You use OnTriggerEnter2D. If your collider not ticked isTrigger field, you can use OnCollisionEnter2D.
And also if your object has Normal (3D) collider you need to use 3D versions of them.
OnTriggerEnter or OnCollisionEnter.
And also you should read this.
UPDATE
After discussion and looking your project problem is your character doesnt hit the destroyer object's collider. It moves with your main camera. (Destroyer object is child object of camera). Because of that when you take your destroyer from camera's child object it works.
Any child object in the heirarchy inherits it's parents movement. So if the collider is on a child object of the camera, it will move when the camera moves.

Getting a NullReferenceException when accessing a component that I've created and retrieved

First of all, how original of me to post another dreaded
NullReferenceException: Object reference not set to an instance of an object
but I have scoured the web looking for a solution for like 2 hours now and have come up with nothing... Here is are the two scripts i have :
GROUNDED:
using UnityEngine;
using System.Collections;
public class GroundCheck : MonoBehaviour {
private Player player;
void Start()
{
player = GetComponent<Player>();
}
void OnTriggerEnter2D(Collider2D col)
{
player.grounded = true;
}
void OnTriggerExit2D(Collider2D col)
{
player.grounded = false;
}
}
PLAYER:
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour {
public float maxSpeed = 3;
public float speed = 50f;
public float jumpPower = 150f;
public bool grounded;
private Rigidbody2D rb2d;
private Animator anim;
// Use this for initialization
void Start () {
rb2d = gameObject.GetComponent<Rigidbody2D>();
anim = gameObject.GetComponent<Animator>();
}
// Update is called once per frame
void Update () {
anim.SetBool("Grounded", grounded);
anim.SetFloat("Speed", Mathf.Abs(Input.GetAxis("Horizontal")));
}
void FixedUpdate()
{
float h = Input.GetAxis("Horizontal");
rb2d.AddForce((Vector2.right * speed) * h);
if (rb2d.velocity.x > maxSpeed)
{
rb2d.velocity = new Vector2(maxSpeed, rb2d.velocity.y);
}
if (rb2d.velocity.x < -maxSpeed)
{
rb2d.velocity = new Vector2(-maxSpeed, rb2d.velocity.y);
}
}
}
The exact error is:
NullReferenceException: Object reference not set to an instance of an object
GroundCheck.OnTriggerEnter2D (UnityEngine.Collider2D col)
(atAssets/scripts/GroundCheck.cs:15)
Here is my scene:
Here is my boxcollider (if it helps):
If both of the GroundCheck and PLAYER classes are on same GameObject then change the Start() method of GroundCheck class like this:
void Start()
{
player = gameObject.GetComponent<Player>();
}
If they are not on same GameObject then use the following code:
void Start()
{
GameObject playerObj = GameObject.Find("Name of gameObject that player script is in that");
player = playerObj.GetComponent<Player>();
}
In PLAYER class add static modifier to defination of grounded:
public static bool grounded;
Your ground check script isn't on the same object as the player script, that means you can't use getcomponent to get the player script. So you haven't set the player var to anything which is causing the error. Set the player var to the gameobject that has the player script in the editor then in your start method use player.GetComponent();
void OnTriggerEnter2D(Collider2D col) <-- in collider param request gameObject, getcomponent to col is prefered, only control if object collision is player. col.gameObject.getcomponent<Player>().grounded=true;
if(col.Name.Equals("Player")
{
col.gameObject.getcomponent<Player>().grounded=true;
}
I had a similar problem. I hope it's helps
http://docs.unity3d.com/ScriptReference/Collision2D.html
Collider2d have gameobject component, trigger enter get Collider this object.
in http://docs.unity3d.com/ScriptReference/Collider2D.OnCollisionEnter2D.html
see example use in collider (not trigger is only example) to use, acces gameObject.
Not necessary findtag when object(player) is passing for parameter in event OnTriggerEnter, Exit or Stay

Categories

Resources