Hey guys,
When I tried to load the “Enemy Maneuver” script in the GameObject of “Enemy Ship”, it failed to be loaded as the console saying I haven’t added a Audio Source to the game object of “Enemy Ship”, but the problem is, this has been done in previous step already- as you can see in the below picture, i’ve attached “Bolt Enemy” into “Shot” in the inspector, and i’ve checked several times that the audio source of “Enemy weapon” is well attached in “Bolt Enemy”. More importantly, it ran okay before (i’ve tested it) and it started to pop out this problem when the script of “Enemy Maneuver” tends to be loaded.
Any ideas do you reckon the problem might be? thanks a lot.
I am running Unity v5.6.1f1 on WIN7 PC.
alt text
your problem is your class name is movement _enemy and your file name is EnemyManuever. your file name and class name must be the same.
The error message says that there is no AudioSource attached to Enemy Ship, and in your text you say you attach one to the Bolt Enemy object that is referenced by your Enemy Ship. This is exactly where the problem is. Unity won’t transitively do GetComponent. If you look for a component on object X, it has to be on object X and not object Y with Y being referenced on X.
I don’t know how it’s supposed to have run before but not with the configuration you described in your text.
Either way… you’d have to go through the chain of references to get to the GameObject that actually has your AudioSource attached. Like
enemyShip.GetComponent<Weapon_Enemy>().shotSpawn.GetComponent<AudioSource>().Play();
As you can probably imagine, this is not something you want to have in your code.
To avoid this, you have to think about what you’re trying to do on a semantic level and how you could improve that. Why is there a script on an object that wants to trigger an AudioSource that it not only doesn’t directly know? And even worse, the object it does know doesn’t directly know either?
There usually is a way of remodelling your context in order to keep this from happening.
The simplest way would usually be to pass the reference of the spawned object to the script that
actually needs it. But it’s worth trying to come up with other solutions as well.
I’ve attached the two section of codes here - former one is the EnemyManeuver, latter one is how the audio played. Thanks.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement_Enemy : MonoBehaviour {
private float newManeuver;
private float targetManeuver;
public Vector2 Start_wait;
public Vector2 maneuverTime;
public Vector2 maneuverWait;
public float swing;
public float speed;
public Rigidbody rb;
public Boundary b;
public float tilt;
public float xMin, xMax, zMin, zMax;
private Vector3 currentSpeed;
void Start () {
rb = GetComponent<Rigidbody> ();
StartCoroutine (Evasion ());
currentSpeed = rb.velocity;
}
IEnumerator Evasion () {
yield return new WaitForSeconds (Random.Range(Start_wait.x, Start_wait.y));
while (true) {
targetManeuver = Random.Range (1, swing) * - Mathf.Sign(transform.position.x);
yield return new WaitForSeconds (Random.Range(maneuverTime.x, maneuverTime.y));
targetManeuver = 0;
yield return new WaitForSeconds (Random.Range(maneuverWait.x, maneuverWait.y));
}
}
void FixedUpdate () {
newManeuver = Mathf.MoveTowards (rb.velocity.x, targetManeuver, Time.deltaTime * speed); //current value move towards the target value
rb.velocity = new Vector3(newManeuver, 0.0f, currentSpeed.z);
rb.position = new Vector3(Mathf.Clamp(rb.position.x, b.xMin, b.xMax), 0.0f, Mathf.Clamp(rb.position.z, b.zMin, b.zMax));
rb.rotation = Quaternion.Euler(0.0f, 0.0f, rb.velocity.x * - tilt);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Weapon_Enemy : MonoBehaviour {
private AudioSource audio;
public Transform shotSpawn;
public GameObject shot;
public float fireRate;
public float nextFire;
void Start (){
InvokeRepeating ("Fire", nextFire, fireRate);
}
// Update is called once per frame
void Fire () {
Instantiate (shot, shotSpawn.position, shotSpawn.rotation);
audio = GetComponent<AudioSource> ();
audio.Play ();
}
}