I'm having some problems on instantiating an enemy in unity, it gives me always this error setDestination" can only be called on an active agent that has been placed on a NavMesh., and then it places a 2d model somewhere in my map
public GameObject enemy;
public Transform spawn;
// Start is called before the first frame update
void Start()
{
spawnNew();
}
void spawnNew() {
Instantiate(enemy, spawn.transform.position, Quaternion.identity);
}
After you have spawned an enemy, call the NavMeshAgent.Warp() function to position the agent on the desired position, which of course must be inside the navmesh.
Related
I am making a space invaders game, and have a script attached to a separated gameObject that instantiates Enemies. I can drag in the prefab and make it work, but then I want the enemies to spawn bullets themselves, with the bullet being a prefab.
I have started with just creating a variable for the bullet, but how would I access the prefab in script, as if I just drag it into the prefab, it won't be useable after the prefab is instantiated.
GameObject bullet;
void Start() {
bullet = // Insert Function to access prefab
}
Thanks
If you put your prefab in a Root Folder named "Resources" you can load prefabs from there like this:
Instantiate(Resources.Load("YourBulletPrefab"));
But you can also make the variable public...
public GameObject bullet; // or use private + [SerializeField]
...and then in Inspector, drag your Prefab in. No need to initialize it in Start() in that case.
I usually solve this by adding a public GameObject bullet variable to the "enemy" script AND the "enemy spawner" script. In the inspector you give reference to the "enemy spawner" to access the bullet prefab. And then, when you spawn an enemy, you pass its reference to the enemy. Something like this:
Enemy script:
class Enemy
{
public GameObject bullet;
private Shoot()
{
//Shoot bullet
}
}
EnemySpawner script:
class EnemySpawner
{
public GameObject enemy;
public GameObject bullet;
private Spawn()
{
GameObject newEnemy = Instantiate(enemy);
enemy.GetComponent<Enemy>().bullet = bullet;
}
}
By doing so, you will be able to access the bullets later as well.
I am following an Unity tutorial. I face a problem when trying to detect collision in the game. This is the error:
NullReferenceException: Object reference not set to an instance of an object
This is the script:
using UnityEngine;
public class Collide : MonoBehaviour
{
public Movement movement; // A reference to our PlayerMovement script
// This function runs when we hit another object.
// We get information about the collision and call it "collisionInfo".
void OnCollisionEnter(Collision collisionInfo)
{
// We check if the object we collided with has a tag called "Obstacle".
if (collisionInfo.collider.tag == "Obstacle")
{
movement.enabled = false; // Disable the players movement.
Debug.Log("Coollision occured");
}
}
}
As i saw in the second image you have not added the movement reference to the movement field. At the same in the script also you are not assigning the reference. Try to assign at editor or you can create object.
The reason is you have not set the movement field in your Collide component.
You can add it from the Unity Editor or add the following line in your Start function of Collide :
void Start()
{
movement = GetComponent<Movement>();
}
I have got my Hand Prefab attached to Player Prefab as a child.
I want to spawn Gun Prefab in my Hand Prefab(Players child).
Is this way i can do this from Hand level?
At the moment I am spawning Gun from Hand, but it works only on single Player. While i play with 2 players, in the moment of spawning a Gun. Game crashes for client. This is the Error im getting:
NullReferenceException: Object reference not set to an instance of an object
UnityEngine.Networking.NetworkServer.SpawnWithClientAuthority (UnityEngine.GameObject obj, UnityEngine.Networking.NetworkConnection conn) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServer.cs:1565)
HandHolder.CmdGetGun () (at Assets/Scripts/HandHolder.cs:27)
HandHolder.Update () (at Assets/Scripts/HandHolder.cs:19)
Thats my Code for Hand:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class HandHolder : NetworkBehaviour {
[SerializeField] GameObject gun;
private GameObject playerGun;
// Update is called once per frame
void Update () {
if(GetComponentInParent<NetworkIdentity>().isLocalPlayer)
{
if (playerGun)
{
playerGun.transform.position = new Vector3(transform.position.x, transform.position.y, transform.position.z - 1);
playerGun.transform.rotation = transform.rotation;
}
else if (Input.GetKeyDown(KeyCode.I))
{enter code here
CmdGetGun();
}
}
}
// [Command]
public void CmdGetGun()
{
playerGun = Instantiate(gun, transform.position, transform.rotation) as GameObject;
NetworkServer.SpawnWithClientAuthority(playerGun, GetComponentInParent<NetworkIdentity>().connectionToClient);
}
}
When im adding [Command] before CmdGetGun() method, in the moment of spawning a gun i got this error:
There is no NetworkIdentity on this object. Please add one.
UnityEngine.Networking.NetworkBehaviour:get_isServer()
HandHolder:CallCmdGetGun()
HandHolder:Update() (at Assets/Scripts/HandHolder.cs:19)
But when i add NetworkIdentity to my child Hand Prefab it shows me that hasAuthority, isLocalPlayer is False for both Hand and Player.
I have no idea how can i spawn Gun in Hand Prefab.
Here are Components and tree:
Your network object is your Player, so you need to route your network functions through your player.
Call CmdGetGun()* in your player class and call it from there.
*CmdGetGun() should not be a [Command]
Optionally, you can call CmdGetGun as a Command, but then you don't want networked instantiation, just local (the command will be called all clients, so all clients will locally create the gun).
EDIT
CmdGetGun will create the object on all clients, but it won't parent it like you are expecting. You should probably try the second approach I mentioned (call it as a command, but instantiate locally)
I have a prefab that is instantiated when the user buys the item from my In-game store, how ever many is instantiated, the all of prefab has a start position of a certain position. The prefab can be dragged around the scene using this TouchScript package I found online! My issue: I want to play the prefab's animation every time the user is dragging the prefab around the screen, I attempted this by creating a RaycastHit2D function that would allow me to detect if the user has clicked on the prefab's collider, script below:
if (Input.GetMouseButtonDown (0)) {
Vector2 worldPoint = Camera.main.ScreenToWorldPoint (Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast (worldPoint, Vector2.zero);
if (hit.collider != null) {
if (this.gameObject.name == "Item5 (1)(Clone)" +item5Increase.i) {
monkeyAnim.SetBool ("draging", true);
Debug.Log (hit.collider.name);
}
} else {
monkeyAnim.SetBool ("draging", false);
}
}
However if I were to buy more than one prefab, all instantiated prefabs will play it's animation when I start to drag only one of the instantiated prefabs, hope I'm making sense. Can some one help me? Thank you!
I faced a similar issue with platforms in my 2D game. The solution I would suggest is to create a GameObject that acts as the current item you wish to animate, and a LayerMask that acts as a filter for which objects your raycast can hit. You can use this LayerMask in conjunction with the Physics2D.Raycast API, which has an overload method that takes a LayerMask as a parameter.
Start by creating a new layer, which can be done by going to the top right of an object in your scene and accessing the "Layer" box. Once you've created a new layer (I called mine "item"), make sure your prefab's layer is assigned correctly.
Then, create an empty object in your scene, and attach this script to it. On that object you will see a dropdown menu that asks which layers your raycast should hit. Assign it the "item" layer; this ensures that your raycast can only hit objects in that layer, so clicking on anything else in your game will produce no effect.
using UnityEngine;
public class ItemAnimation : MonoBehaviour
{
private GameObject itemToAnimate;
private Animator itemAnim;
[SerializeField]
private LayerMask itemMask;
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
CheckItemAnimations();
}
else if (Input.GetMouseButtonUp(0) && itemToAnimate != null) //reset the GameObject once the user is no longer holding down the mouse
{
itemAnim.SetBool("draging", false);
itemToAnimate = null;
}
}
private void CheckItemAnimations()
{
Vector2 worldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector2.zero, 1, itemMask);
if (hit) //if the raycast hit an object in the "item" layer
{
itemToAnimate = hit.collider.gameObject;
itemAnim = itemToAnimate.GetComponent<Animator>();
itemAnim.SetBool("draging", true);
Debug.Log(itemToAnimate.name);
}
else //the raycast didn't make contact with an item
{
return;
}
}
}
I am instantiating enemy(Clones) from an enemy GameObject in Unity using c#. I have written a destroy function to delete only the enemy(Clones) when the bullet hits them. Unity renders the enemy GameObject on screen.
I cannot destroy this GameObject in runtime since unity will not instantiate any more enemy(Clones). Please help me not render the base enemy GameObject as it serves no purpose on screen.
Note: Enemy is scripted to walk towards player position and hence keeping the object outside the screen is pointless.
Please Help
here is a snippet of my code. I dragged the enemy GameObject into the Project section. Now it has created 2 Enemy objects on screen
public Rigidbody2D enemy;
void enemySpawn()
{
Rigidbody2D enemyInstance;
enemyInstance = Instantiate(enemy, new Vector3(Random.Range (2,8), Random.Range (-4,4), 0), Quaternion.Euler(new Vector3(0,0,0))) as Rigidbody2D;
}
Make your enemy into prefab this can be done by dragging the gameObject into projectview.
You can instantiate new enemies from the prefabs with any gameObject. For example an empty one without any rendering components.
Instantiate can be done with this kind of script:
public GameObject enemy;
void InstantiateEnemy () {
GameObject enemyClone= (GameObject) Instantiate(enemy, transform.position, transform.rotation);
}
Just set the public GameObject in the editor and call the InstantiateEnemy function from somewhere.