I tried looking up all I could about how nested classes might be handled different in Unity, and found surprisingly little available. Thus I figured I’d get better results just asking the question directly.
I’m relatively new to coding, and am working on making an ARPG, and am trying to script the ability system for the game. I made a base ability class that contains some consistent variables and methods all abilities would use (like startups and cooldowns), and created a few inherited classes to handle more specific tasks such as attacking and movement. The problem lies in determining how to implement these abilities.
The first approach I tried involved creating a script for each ability, which inherited from these expanded ability classes, like a walk class that inherits from the movement abiltiy class. This worked, but seemed like it would quickly become completely unmanageable (for instance making an ability script for each swing of a sword combo).
Instead, I’ve recently been trying to see if nested classes might work for my purpose. I figured I could create the classes from the previous separate scripts files as nested classes within the relevant script that would use it, such as a movement class which has access to all the movement actions a character might use, resulting in the piece of code below. The problem seems to lie in initializing the nested classes themselves, as whenever I run the scene in unity, I receive this error from Unity: “Can’t add script behaviour . The scripts file name does not match the name of the class defined in the script!”
Does the problem lie in how I’m using AddComponent? How does one actually create an instance of a nested class in Unity?
Thanks for whatever help you might be able to lend.
using UnityEngine;
using System;
using System.Collections;
public class BaseMovement : MonoBehaviour
{
public enum MoveState {
Idle,
Turning,
Aiming,
Walking,
Running,
Dodging
}
#region Class Variables and Members
//Specialization
private Transform _user;
private CharacterController _body;
private MoveState _state;
//Movement Abilities
protected BaseMovement.BaseAim aim;
protected BaseMovement.BaseTurn turn;
protected BaseMovement.BaseWalk walk;
protected BaseMovement.BaseRun run;
protected BaseMovement.BaseDodge dodge;
//Internal Coordination
private Vector3 _moveDir;
private Vector3 _lookDir;
#endregion
#region Getters and Setters
public MoveState State {
get {return _state;}
set {_state = value;}
}
public bool Grounded {
get {return _grounded;}
set {_grounded = value;}
}
public Transform User {
get {return _user;}
set {_user = value;}
}
public BaseMovement.BaseAim Aim
{
get {return aim;}
set {aim = value;}
}
public BaseMovement.BaseTurn Turn
{
get {return turn;}
set {turn = value;}
}
public BaseMovement.BaseWalk Walk
{
get {return walk;}
set {walk = value;}
}
public BaseMovement.BaseRun Run
{
get {return run;}
set {run = value;}
}
public BaseMovement.BaseDodge Dodge
{
get {return dodge;}
set {dodge = value;}
}
#endregion
protected virtual void Awake () {
_user = GetComponent<Transform>();
_body = GetComponent<CharacterController>();
if (_body == null) return;
_state = MoveState.Idle;
_moveDir = Vector3.zero;
_lookDir = Vector3.zero;
aim = gameObject.AddComponent<BaseMovement.BaseAim>();
turn = gameObject.AddComponent<BaseMovement.BaseTurn>();
walk = gameObject.AddComponent<BaseMovement.BaseWalk>();
run = gameObject.AddComponent<BaseMovement.BaseRun>();
dodge = gameObject.AddComponent<BaseMovement.BaseDodge>();
Debug.Log ("MOVEMENT PLUGINS CREATED");
}
private void SetMoveState (BaseMovement.MoveState state) {
_state = state;
}
#region Movement Functions
public void Gravity () {
Vector3 down = -Vector3.forward;
Vector3 gravity = new Vector3(0, 0, -10); //strength of gravity
float distanceToGround = 2; //units above map plane to be considered "grounded"
RaycastHit hit;
if (Physics.Raycast (User.position, down, out hit)) {
if (hit.collider.tag == "Ground") {
if (distanceToGround <= hit.distance) {
_grounded = false;
_body.Move(gravity);
} else {
_grounded = true;
}
} else {
Debug.LogWarning("Character did not find any ground");
}
}
}
protected class BaseAim : MovementAbility
{
BaseMovement _movement;
protected override void Awake ()
{
base.Awake ();
_movement = GetComponent<BaseMovement>();
Name = "Aim";
Effect = AimAbility;
Speed = 0.0f;
StartupTime = 0.0f;
DurationTime = 0.0f;
CooldownTime = 0.0f;
}
private void AimAbility (Vector3 target)
{
//_state = MoveState.Aiming;
Vector3 object_pos = Camera.main.WorldToScreenPoint(User.position);
float angle;
target.x = target.x - object_pos.x;
target.y = target.y - object_pos.y;
angle = Mathf.Atan2(target.x, target.y) * Mathf.Rad2Deg;
User.rotation = Quaternion.Euler(0, 0, angle);
}
}
protected class BaseTurn : MovementAbility
{
BaseMovement _movement;
protected override void Awake ()
{
base.Awake ();
_movement = GetComponent<BaseMovement>();
Name = "Turn";
Effect = TurnAbility;
Speed = 3.0f;
StartupTime = 0.0f;
DurationTime = 0.0f;
CooldownTime = 0.0f;
}
private void TurnAbility (Vector3 target)
{
//_state = MoveState.Turning;
float aim = Mathf.Atan2(-target.x, target.y) * Mathf.Rad2Deg;
User.rotation = Quaternion.Euler(0, 0, aim);
}
}
protected class BaseWalk : MovementAbility
{
protected override void Awake ()
{
base.Awake ();
Name = "Walk";
Effect = WalkAbility;
Speed = 7.0f;
StartupTime = 0.0f;
DurationTime = 0.0f;
CooldownTime = 0.0f;
}
private void WalkAbility ( Vector3 dir)
{
//_state = MoveState.Walking;
Vector3 moveDir = dir.normalized; //holds direction the character will move in
moveDir *= Speed;
if (Body != null)
Body.Move (moveDir * Time.deltaTime);
else
Debug.Log("No controller to move");
}
}
protected class BaseRun : MovementAbility
{
protected override void Awake ()
{
base.Awake ();
Name = "Run";
Effect = RunAbility;
Speed = 15.0f;
StartupTime = 0.0f;
DurationTime = 0.0f;
CooldownTime = 0.0f;
}
private void RunAbility ( Vector3 dir)
{
//_state = MoveState.Running;
Vector3 moveDir = dir.normalized; //holds direction the character will move in
moveDir *= Speed;
if (Body != null)
Body.Move (moveDir * Time.deltaTime);
else
Debug.Log("No controller to move");
}
}
protected class BaseDodge : MovementAbility
{
protected override void Awake ()
{
base.Awake ();
Name = "Dodge";
Effect = DodgeAbility;
Speed = 40.0f;
StartupTime = 0.0f;
DurationTime = 0.20f;
CooldownTime = 0.0f;
}
private void DodgeAbility (Vector3 dir)
{
//_state = MoveState.Dodging;
Debug.Log ("DODGE ACTIVATED");
Vector3 moveDir = dir.normalized;
moveDir *= Speed;
if (Body != null)
Body.Move (moveDir * Time.deltaTime);
else
Debug.Log("No controller to move");
}
}
#endregion
}