How to set proper animation to prefabs randomly instantiated?
Hello. My script is spawning a random ninja between 4 ninja prefabs. Every ninja shares the same animatorcontroller. Although I try to call each instantiated ninja's animator, the animation just won't run. More spcifically, the parameter I'm trying to change does not change in the condition I set it to change. What's the best way to do this? As I said, I followed these instructions: https://stackoverflow.com/questions/28987002/duplicated-animations-between-prefabs, but it did nothing. I'm a total noob at this. This is my first game and I'm stuck at this point. I'd appreciate some help.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spawner : MonoBehaviour
{
[SerializeField]
public GameObject ninjal;
public GameObject ninjar;
public GameObject ninjau;
public GameObject ninjad;
public float timer = 0;
public float maxtime = 10;
public GameObject[] ninjas;
private int randomprefab;
Animator anim;
public GameObject newninja;
void Start()
{
anim = GetComponent<Animator>();
var ninjal = Resources.Load("NinjaNPCleft Variant") as GameObject;
var ninjar = Resources.Load("NinjaNPCright Variant") as GameObject;
var ninjau = Resources.Load("NinjaNPCup Variant") as GameObject;
var ninjad = Resources.Load("NinjaNPCdown Variant") as GameObject;
float randomnumber = Random.Range(0, 4);
switch (randomnumber)
{
case 0: GameObject.Instantiate(ninjal, ninjal.transform.position, ninjal.transform.rotation); break;
case 1: GameObject.Instantiate(ninjar, ninjar.transform.position, ninjar.transform.rotation); break;
case 2: GameObject.Instantiate(ninjau, ninjau.transform.position, ninjau.transform.rotation); break;
case 3: GameObject.Instantiate(ninjad, ninjad.transform.position, ninjad.transform.rotation); break;
}
}
// Update is called once per frame
void Update()
{
if (timer > maxtime)
{
randomprefab = Random.Range(0, 4);
newninja = Instantiate(ninjas[randomprefab], ninjas[randomprefab].transform.position, ninjas[randomprefab].transform.rotation);
timer = 0;
}
timer += Time.deltaTime;
if (newninja.transform.position.x == 7.2f)
{
newninja.GetComponent<Animator>().SetInteger("attack", 1);
}
}
}
On awake I don't want the ninja spawned to change to attack. But I want the rest of them (those instantiated every 10 seconds) to do so on certain conditions without it influencing the animation of any other ninja that does not meet the condition. I appreciate the patience and sorry if the code is rustic or has any none sense that you may find "insulting" to even show online. Thank you very much.
Hello.
Are you sure the code arrives to the line : newninja.GetComponent<Animator>().SetInteger("attack", 1);
??
The code seems correct... You should debug your code to be sure.
are you sure the trigger is called attack, not atack, or Attack or something else?
Good luck.
Hello. Thank you for your attention! Yes, I made sure I wrote it correctly since I already made that mistake in the past in the same project ahahah. That's the problem. I'm not sure if it even reaches that line. When I change the newninja name to something else right after instantiating it it does in fact change the name of the instantiated object, therefore detecting and ai$$anonymous$$g for the instantiated ninja only. But if I place the animator condition right after instantiating, it will be submitted to the condition of "timer" as well and will not work properly. I'm in a mess here. $$anonymous$$aybe if I change the newninja value to a static one and call the animator condition in a different script.... I don't know. Do you think that this code should work to randomly instantiated objects and only affect each individual then?
Okey, I found a way around it. I created a different script called "NPCBehaviour" that is added to the prefab as soon as it get's instantiated. I also added an offset to the condition (maybe that was the reason it started working, I'm not sure). That script has: void Update() { if (transform.position.x > 7.1 && transform.position.x < 7.3) { anim.SetInteger("attack", 1) } } Thank you for your help and attention and I'm sorry to waste your time. I'm a terrible noob at this still.
Answer by Doctor_ED · May 22, 2019 at 06:42 PM
First of all, if the "newninja" is not altered by another script, then for the first 10 seconds after Start(), it's value is null.Here :
if (newninja.transform.position.x == 7.2f)
{
newninja.GetComponent<Animator>().SetInteger("attack", 1);
}
you are trying to perform actions on null object, so it should throw an "NullReferenceException". To fix that, change your Update() method as follows :
void Update()
{
if (timer > maxtime)
{
randomprefab = Random.Range(0, 4);
newninja = Instantiate(ninjas[randomprefab], ninjas[randomprefab].transform.position, ninjas[randomprefab].transform.rotation);
timer = 0;
if (newninja.transform.position.x == 7.2f)
{
newninja.GetComponent<Animator>().SetInteger("attack", 1);
}
}
timer += Time.deltaTime;
}
Why if (newninja.transform.position.x == 7.2f)
?
Disclaimer :
Naming conventions! (xd)
If you don't do things with them
public GameObject ninjal;
public GameObject ninjar;
public GameObject ninjau;
public GameObject ninjad;
in your other scripts, then it's better to keep them as private. You should make them into array.
var ninjal = Resources.Load("NinjaNPCleft Variant") as GameObject;
var ninjar = Resources.Load("NinjaNPCright Variant") as GameObject;
var ninjau = Resources.Load("NinjaNPCup Variant") as GameObject;
var ninjad = Resources.Load("NinjaNPCdown Variant") as GameObject;
That "var" keyword is as far as I know unnecessary and confusing, as it "looks" like you're creating new variables, but in reality you are not.
You should consider putting your code from Update() to a coroutine.
Thank you for your feedback! The problem was not with the var ninjal,r,u,d. The problem was in the newninja that was instantiated after the 10 seconds. I understand what you mean and you're right. But the condition should not be applied right after it is instantiated, but when it moves to said x position, I must've past the code wrong. Thus I needed it to reach the instantiated ninja after it got instantiated. I think offsetting from x == 7.2f to x>7.1f && x<7.3f would do the work. But I worked it around adding a new script to the instantiated ninja with AddComponent<>() where the position is scanned for that object only. Thank you again! You guys are really fast to answer here in the forum. I appreciate that!
Your answer
Follow this Question
Related Questions
Multiple enemies and no animations 0 Answers
Animate a Prefab and change Clip Properties programmatically 0 Answers
Animate a Prefab and change Clip Properties programmatically 0 Answers
Can't play an animation from the Animator 1 Answer
Problems with using the same Animator Controller on multiple objects. 0 Answers