Forum begins after the advertisement:
NullReferenceException in GetSpawnAngle()
Home › Forums › Video Game Tutorial Series › Creating a Rogue-like Shoot-em Up in Unity › NullReferenceException in GetSpawnAngle()
- This topic has 0 replies, 2 voices, and was last updated 1 day, 6 hours ago by
Alp Apustaja.
-
AuthorPosts
-
July 15, 2025 at 3:11 am #18497::
Hi, so recently I’ve got an error in unity which literally states:
“NullReferenceException: Object reference not set to an instance of an object. ProjectileWeapon.GetSpawnAngle () (at Assets/Scripts/Weapons/ProjectileWeapon.cs:77) ProjectileWeapon.Attack (System.Int32 attackCount) (at Assets/Scripts/Weapons/ProjectileWeapon.cs:42) Weapon.Update () (at Assets/Scripts/Weapons/Weapon.cs:106) ProjectileWeapon.Update () (at Assets/Scripts/Weapons/ProjectileWeapon.cs:11)”
I tried to fix it but to no avail. I did everything according to the tutorial and also I think it’s got to mention that I’m working in unity 6.
Each time the projectiles spawns/fires it shows the same error. After trying to debug I noticed that the movement variable is set to null. I tried to set the movement variable inside the function but the game started freezing after that.
Here are my scripts:
// ProjectileWeapon.cs using UnityEngine;
public class ProjectileWeapon : Weapon {
protected float currentAttackInterval; // what is the time in between attacks protected int currentAttackCount; // Number of times this attack will happen. protected override void Update() { base.Update(); // Otherwise, if the attack interval goes from above 0 to below, we also call attack. if (currentAttackInterval > 0) { currentAttackInterval -= Time.deltaTime; if (currentAttackInterval <= 0) Attack(currentAttackCount); } } public override bool CanAttack() { if (currentAttackCount > 0) return true; return base.CanAttack(); } protected override bool Attack(int attackCount = 1) { // If no projectile prefab is assigned, leave a warning message. if (!currentStats.projectilePrefab) { //Debug.LogWarning(string.Format("Projectile prefab has not been set for {0}", name)); Debug.LogWarning($"Projectile prefab has not been set for {name}"); currentCooldown = data.baseStats.cooldown; return false; } // Can we attack? if (!CanAttack()) return false; // Otherwise, calculate the angle and offset of our spawned projectile. float spawnAngle = GetSpawnAngle(); // And spawn a copy of the projectile. Projectile prefab = Instantiate( currentStats.projectilePrefab, owner.transform.position + (Vector3)GetSpawnOffset(spawnAngle), Quaternion.Euler(0, 0, spawnAngle) ); prefab.weapon = this; prefab.owner = owner; // Reset the cooldown only if this attack was triggered by cooldown. if (currentCooldown <= 0) currentCooldown += currentStats.cooldown; attackCount--; // Do we perform another attack? if (attackCount > 0) { currentAttackCount = attackCount; currentAttackInterval = data.baseStats.projectileInterval; } return true; } // Gets which direction the projectile should face when spawning. protected virtual float GetSpawnAngle() { if (movement == null) { Debug.LogWarning("null pusty"); } return Mathf.Atan2(movement.lastMovedVector.y, movement.lastMovedVector.x) * Mathf.Rad2Deg; } // Generates a random point to spawn the projectile on, and // rotates the facing of the point by spawnAngle. protected virtual Vector2 GetSpawnOffset(float spawnAngle = 0) { return Quaternion.Euler(0, 0, spawnAngle) * new Vector2( Random.Range(currentStats.spawnVariance.xMin, currentStats.spawnVariance.xMax), Random.Range(currentStats.spawnVariance.yMin, currentStats.spawnVariance.yMax) ); }
}
//Weapon.cs using System.Collections; using System.Collections.Generic; using UnityEngine;
/// <summary> /// Component to be attached to all Weapon prefabs. The Weapon prefab works together with the WeaponData /// ScriptableObjects to manage and run the behaviours of all weapons in the game. /// </summary> public abstract class Weapon : Item { [System.Serializable] public struct Stats { public string name, description;
[Header("Visuals")] public Projectile projectilePrefab; // If attached, a projectile will spawn every time the weapon cools down. public Aura auraPrefab; // If attached, an aura will spawn when weapon is equipped. public ParticleSystem hitEffect; public Rect spawnVariance; [Header("Values")] public float lifespan; // If 0, it will last forever. public float damage, damageVariance, area, speed, cooldown, projectileInterval, knockback; public int number, piercing, maxInstances; // Allows us to use the + operator to add 2 Stats together. // Very important later when we want to increase our weapon stats. public static Stats operator +(Stats s1, Stats s2) { Stats result = new Stats(); result.name = s2.name ?? s1.name; result.description = s2.description ?? s1.description; result.projectilePrefab = s2.projectilePrefab ?? s1.projectilePrefab; result.auraPrefab = s2.auraPrefab ?? s1.auraPrefab; result.hitEffect = s2.hitEffect == null ? s1.hitEffect : s2.hitEffect; result.spawnVariance = s2.spawnVariance; result.lifespan = s1.lifespan + s2.lifespan; result.damage = s1.damage + s2.damage; result.damageVariance = s1.damageVariance + s2.damageVariance; result.area = s1.area + s2.area; result.speed = s1.speed + s2.speed; result.cooldown = s1.cooldown + s2.cooldown; result.number = s1.number + s2.number; result.piercing = s1.piercing + s2.piercing; result.projectileInterval = s1.projectileInterval + s2.projectileInterval; result.knockback = s1.knockback + s2.knockback; return result; } // Get damage dealt. public float GetDamage() { return damage + Random.Range(0, damageVariance); } } protected Stats currentStats; public WeaponData data; protected float currentCooldown; protected PlayerMovement movement; // Reference to the player's movement. // For dynamically created weapons, call initialise to set everything up. public virtual void Initialise(WeaponData data) { movement = GetComponentInParent<PlayerMovement>(); if (!movement) { Debug.LogWarning("suck w weapon.cs"); } else { Debug.LogWarning("działa tutaj to kijostwo heheh"); } base.Initialise(data); this.data = data; currentStats = data.baseStats; currentCooldown = currentStats.cooldown; } protected virtual void Awake() { // Assign the stats early, as it will be used by other scripts later on. if (data) currentStats = data.baseStats; } protected virtual void Start() { // Don't initialise the weapon if the weapon data is not assigned. if (data) { Initialise(data); } } protected virtual void Update() { currentCooldown -= Time.deltaTime; if (currentCooldown <= 0f) //Once the cooldown becomes 0, attack { Attack(currentStats.number); } } // Levels up the weapon by 1, and calculates the corresponding stats. public override bool DoLevelUp() { base.DoLevelUp(); // Prevent level up if we are already at max level. if (!CanLevelUp()) { Debug.LogWarning(string.Format("Cannot level up {0} to Level {1}, max level of {2} already reached.", name, currentLevel, data.maxLevel)); return false; } // Otherwise, add stats of the next level to our weapon. currentStats += data.GetLevelData(++currentLevel); return true; } // Lets us check whether this weapon can attack at this current moment. public virtual bool CanAttack() { return currentCooldown <= 0; } // Performs an attack with the weapon. // Returns true if the attack was successful. // This doesn't do anything. We have to override this at the child class to add a behaviour. protected virtual bool Attack(int attackCount = 1) { if (CanAttack()) { currentCooldown += currentStats.cooldown; return true; } return false; } // Gets the amount of damage that the weapon is supposed to deal. // Factoring in the weapon's stats (including damage variance), // as well as the character's Might stat. public virtual float GetDamage() { return currentStats.GetDamage() * owner.CurrentMight; } // For retrieving the weapon's stats. public virtual Stats GetStats() { return currentStats; }
}
Thanks for help in advance!
July 15, 2025 at 3:21 am #18498::The error you’re encountering,
NullReferenceException
, usually indicates that you’re trying to access a member of an object that hasn’t been initialized. In your case, the error is occurring in theGetSpawnAngle
method ofProjectileWeapon
, where you’re trying to accessmovement.lastMovedVector
.Since you’ve mentioned that the
movement
variable is null, it seems that thePlayerMovement
component is not being found in the parent object. Here are a few things to check and try:-
Ensure PlayerMovement is Attached: Make sure that the
PlayerMovement
component is indeed attached to the parent GameObject of yourProjectileWeapon
. If it’s not,GetComponentInParent()
will return null. -
Check Scene Hierarchy: Confirm the hierarchy in the Unity Inspector to ensure that your
ProjectileWeapon
script is attached to a GameObject that has a parent containing thePlayerMovement
script. -
Debugging Movement Initialization: You can add some debug logs in the
Initialise
method to confirm whether themovement
variable is being set correctly:public virtual void Initialise(WeaponData data) { movement = GetComponentInParent(); if (movement == null) { Debug.LogWarning("PlayerMovement component not found in parent hierarchy."); } else { Debug.Log("PlayerMovement component found: " + movement); } // Rest of your initialization... }
-
Assign Movement Before Attack: If you find that the
movement
variable is sometimes null at the time of the attack, you may want to ensure that it is always initialized and not null. You could check and reassign it in theAttack
method:protected override bool Attack(int attackCount = 1) { movement = GetComponentInParent(); // Ensure it's assigned if (movement == null) { Debug.LogError("PlayerMovement component is still null in Attack method."); return false; // Prevent further execution } // Rest of your attack logic... }
-
Potential Freezing Issue: If you tried to set the
movement
variable inside a function and it caused the game to freeze, ensure that you are not creating a recursive call or a loop where the method keeps calling itself repeatedly. -
Check for Multiple Instances: If you have multiple instances of the
ProjectileWeapon
, ensure that each one is either correctly assigned its ownPlayerMovement
or that the hierarchy is set up so that the component can be found properly. -
Use Unity’s Inspector: You can also create public or serialized fields for
PlayerMovement
and assign it directly in the Inspector, which might help avoid null references.
By following these steps, you should be able to identify and resolve the
NullReferenceException
. If problems persist, let me know, and we can further investigate! -
-
AuthorPosts
- You must be logged in to reply to this topic.