OOP: calling overridden method C#

Started by
4 comments, last by Sacaldur 8 years, 9 months ago

Posting here and hoping to find an answer to this smile.png

I'm new to OOP and right now running across some problems. I'm trying to call a few methods when you press a certain key, but when I press that key, absolutely nothing happens.

Here is the class I use to check what keys are being pressed and what method will be called. Every method I'm calling doesn't get executed. Tried a different way around with the 'Run' method. By switching a bool when you press the run key, 'movement' will be multiplied by a number, but that neither does anything.


     using UnityEngine;
     using System.Collections;
     using System.Collections.Generic;
     
     public class Player : MonoBehaviour
     {
         public PlayerShape currentShape;
         public GameObject terrain;
     
         public KeyCode forward;
         public KeyCode backward;
         public KeyCode left;
         public KeyCode right;
         public KeyCode crouch;
         public KeyCode jump;
         public KeyCode run;
         public KeyCode toggleAlwaysRun;
         public KeyCode fightReady;
         public KeyCode hit;
         public float horizontalSpeed = 10f;
         public float verticalSpeed = 10f;
         public KeyCode shapeShift;
     
         void Awake()
         {
             currentShape = new SpartanKing();    
         }
         void Update()
         {
             currentShape.isRunning = Input.GetKey(run);
             if (Input.GetKey(run))
             {
                 currentShape.isRunning = true;
                 currentShape.Run();
                 Debug.Log("is running");
             }
     
             if (Input.GetKey(jump))
             {
                 currentShape.Jump();
             }
     
             if (Input.GetKeyDown(hit))
             {
                 currentShape.Attack();
             }
     
             if (Input.GetKey(shapeShift))
             {
                 ShapeShift();
             }
             currentShape.Smooth();
     
         }
     
     
         public virtual void ShapeShift()
         {
             Vector3 previousPos = currentShape.transform.position;
             Quaternion previousRot = currentShape.transform.rotation;
             Destroy(currentShape);
             //currentShape = Instantiate(_player, previousPos, previousRot);
         }
     }
     

The abstract class:


 using UnityEngine;
 using System.Collections;
 
 
 public abstract class PlayerShape : MonoBehaviour
 {
     public float speed;
     public int jumpHeight;
     public Animator animatorComp;
     public Vector3 movement;
 
     public bool isRunning;
 
     // When pressing WASD keys
     public abstract void Walk();
     // When pressing WASD keys and shift at the same time
     public abstract void Run();
     // When pressing space
     public abstract void Jump();
     // When pressing L-mouse
     public abstract void Attack();
     // When pressing R-mouse
     public abstract void Block();
 
     public virtual void Smooth()
     { 
     
     }
 }

And the class that inherits the abstract class:


     public class SpartanKing : PlayerShape 
     {
         void Start()
         {
             animatorComp = this.GetComponent<Animator>();
             speed = 2.2f;
             jumpHeight = 500;
         }
     
         void Update()
         {
             AnimatorStateInfo stateInfo = animatorComp.GetCurrentAnimatorStateInfo(0);
             float mouseX = Input.GetAxis("Mouse X");
             transform.Rotate(0, mouseX * 5f, 0);
             movement = Input.GetAxis("Vertical") * Vector3.forward * speed + Input.GetAxis("Horizontal") * Vector3.right * speed;
             if (isRunning)
             {
                 Debug.Log("Currently running, modifier applied");
                 movement.z *= 3.0f;
                 movement.x *= 1.5f;
             }
             transform.Translate(movement * Time.deltaTime);
             animatorComp.SetFloat("Speed", movement.magnitude / 5);
     
         }
     
         // When pressing WASD keys
         public override void Walk()
         {
             
         }
     
     
         // When pressing WASD keys and shift at the same time
         public override void Run()
         {
             movement.z *= 3.0f;
             movement.x *= 1.5f;
         }
     
         // When pressing space
         public override void Jump()
         {
             if (!animatorComp.GetBool("IsJumping"))
             {
                 this.GetComponent<Rigidbody>().AddForce(Vector3.up * jumpHeight);
                 animatorComp.SetBool("IsJumping", true);
             }
         }
     
         // When pressing L-mouse
         public override void Attack()
         {
             animatorComp.SetTrigger("IsAttacking");
         }
     
         // When pressing R-mouse
         public override void Block()
         { 
         
         }
         public override void Smooth()
         {
             transform.Translate(movement * Time.deltaTime);
             animatorComp.SetFloat("Speed", movement.magnitude / 5);
         }
     }
Advertisement

The problem is in your awake function:


 void Awake()
{
  currentShape = new SpartanKing();    
}

CurretnShape is not attached to any GameObject, so transform that is accessed in the Smooth() function doesn't really exist.

What you need to do instead is:


void Awake()
{
    currentShape = AddComponent<SpartanKing>();
}

This will attach the new component to the gameobject

Ah yes that makes sense, thanks a lot! smile.png

Had to do it slightly different though, since the Player class and SpartanKing class are attached to different gameobjects:


currentShape = GameObject.Find("SpartanKing").GetComponent<SpartanKing>();
You should, whenever possible, assign the required GameObject instead of searching for it in the scene. This way, some one else could see the dependency in the inspector, since you have to assign the GameObject. (And it should be faster this way.)
If it's not possible (the GameObjects are in difference Scenes), you should make the GameObjet's name editable through the inspector.

Besides that: why are you using Keycodes? You can use the Axes of the input system as buttons as well, and you should do so.
Furthermore you check for inputs in the "Player" and in the "SpartanKing" Component, with the Player forwarding the informations to the PlayerShape (and thus to the SpartanKing). Only one of them should handle the input. (So you would only need to replace the "Player-Input"-Component by a "AI-Input"-Component.)

The best way is to write a component manager to manage these component, his will ensure that all component be added.


public class SpartanKing : PlayerShape 
{
}


public class PlayerData : MonoBehaviour 
{
}


public class ComponentManager : MonoBehaviour
{
    void Start()
    {
        Addcomponent<SpartanKing>();
        Addcomponent<PlayerData>();
       //and so on
    }
}


public class Player : MonoBehaviour
{


    void Start()
    {
        Addcomponent<ComponentManager>();
    }
}

https://github.com/ketoo/NoahGameFrame [A fast, scalable, distributed game server framework for C++]

@kytoo:
If all components are assigned to the same GameObject, you should instead use the RequireComponent-Attribute.
public class SpartanKing : PlayerShape 
{
}


public class PlayerData : MonoBehaviour 
{
}

[RequireComponent(typeof(SpartanKing))]
[RequireComponent(typeof(PlayerData))]
public class Player : MonoBehaviour
{
    void Start()
    {
        
    }
}
Unity will automatically assign the required components, as long as it's possible to assign them. Otherwise - an abstract class is required, such as "Collider" - you'll get an error message while trying to assign the component to a GameObject.

This topic is closed to new replies.

Advertisement