- Home /
C# Inheritance, base class attributes, override and null object
Hi, Could somebody advice me how to fix my problem? I tryed to use Composition of Parachute for my Player and Enemy Class, but I have small problems. You can find 5 scripts below. After initialization:
base.parachute = new Parachute(this.gameObject, 1);
My variable 'parachute' is always empty. I don't know why, because the constructor of the class Parachute is working properly. When I put Debug.Log into Parachute constructor it is displaying the message.
The funniest thing is that when I remove the
if(parachute != null)
My code is working. The parachute is slowing objects etc, but what if I would like to create second enemy without parachute. It should have the checking if parachute is null. Any ideas?
Thank you in advance for your help. I hope you will give me some advice.
BaseObject Script
using UnityEngine;
using System.Collections;
public abstract class BaseObject : MonoBehaviour {
public string a = "test string for all objects";
protected Parachute parachute;
protected virtual void Awake()
{
}
protected virtual void Start()
{
}
protected virtual void Update()
{
}
}
Player Script
using UnityEngine;
using System.Collections;
public class Player : BaseObject {
protected override void Awake ()
{
base.Awake();
}
protected override void Start () {
base.Start();
base.parachute = new Parachute(this.gameObject, 1);
}
protected override void Update () {
base.Update();
if(parachute != null)
{
if(parachute.Duration > 0)
{
if(!parachute.ParachuteEnabled)
{
if(Input.GetButtonDown("Jump"))
{
parachute.DoParachute();
}
} else
base.parachute.Update();
}
}
}
}
Enemy Script using UnityEngine; using System.Collections;
using UnityEngine;
using System.Collections;
public abstract class Enemy : BaseObject {
protected virtual void Awake()
{
base.Awake();
}
protected virtual void Start()
{
base.Start();
}
protected override void Update()
{
base.Update();
}
}
Bomb Script
using UnityEngine;
using System.Collections;
public class Bomb : Enemy {
protected override void Awake()
{
base.Awake();
parachute = new Parachute(this.gameObject, 5);
}
protected override void Start()
{
base.Start();
}
protected override void Update () {
base.Update();
if(parachute != null)
{
if(parachute.Duration > 0)
{
if(!parachute.ParachuteEnabled)
{
if(Input.GetMouseButton(1))
{
parachute.DoParachute();
}
} else
base.parachute.Update();
}
}
}
}
Parachute Script using UnityEngine; using System.Collections; using System.Collections.Generic;
public class Parachute : MonoBehaviour {
private GameObject go;
private float duration;
public float Duration{
get { return duration; }
}
private float orginalDrag;
private float timer;
private bool parachuteEnabled;
public bool ParachuteEnabled{
get { return parachuteEnabled; }
}
private List<float> durations = new List<float>()
{
1f, 2f, 3f, 4f, 5f, 6f
};
public Parachute(GameObject go, int lvl)
{
this.go = go;
this.duration = durations[lvl];
this.orginalDrag = go.rigidbody2D.drag;
}
public void DoParachute()
{
parachuteEnabled = true;
go.rigidbody2D.drag = 20;
}
// Update is called once per frame
public void Update () {
if(parachuteEnabled)
{
timer += Time.deltaTime;
if(timer > Duration)
{
go.rigidbody2D.drag = orginalDrag;
timer = 0;
parachuteEnabled = false;
}
}
}
}
Answer by RudyTheDev · Dec 21, 2014 at 01:07 PM
You don't create MonoBehaviour
classes with new()
-- you use Unity's AddComponent<>
and attach them to GameObject
s. They're not supposed to exist separately. You should have gotten a message about this in the output log.
That said, it will still create an instance. And your base.parachute
isn't actually null
, but it returns null
on equality comparison (like it does for destroyed game objects). If you tried to access it, it will actually work. Though, this is no good if you need to do actual null
comparison.
See this example:
public class TestTheClass : MonoBehaviour
{
void Start()
{
SomeClass someClass = new SomeClass();
Debug.Log(someClass);
Debug.Log(someClass.x);
}
}
public class SomeClass : MonoBehaviour
{
public int x = 2;
public SomeClass()
{
x = 5;
}
}
It will output:
null
UnityEngine.Debug:Log(Object)
sdhgf:Start() (at Assets/sdhgf.cs:9)
5
UnityEngine.Debug:Log(Object)
sdhgf:Start() (at Assets/sdhgf.cs:10)
Thank you very much! It is working now. Ins$$anonymous$$d of using new Class(); I'm using AddComponent; and later: myClass = GetComponent() as Class;
AddComponent
returns the component you added, so you can store it then ins$$anonymous$$d of GetComponent
ing later.
Just a little snippet from the Unity 5 info, on AddComponent
AddComponent(string), when called with a variable cannot be automatically updated to the generic version
AddComponent< T >()
.
In such cases the API Updater will replace the call with a call to APIUpdaterRuntimeServices.AddComponent(). This method is meant to allow you to test your game in editor mode (they do a best effort to try to resolve the type at runtime) but it is not meant to be used in production, so it is an error to build a game with calls to such method). On platforms that support Type.GetType(string) you can try to use GetComponent(Type.GetType(typeName)) as a workaround.
Your answer
Follow this Question
Related Questions
inheritance - instance variable problem? 4 Answers
efficient way to make RTS building instances 2 Answers
C# Conception - Hide inherited members and functions 1 Answer
Is Instance Of 3 Answers