Script access via GetComponent typecast problem c#

Hey folks! I can’t seem to find the answer to this problem…

For some context, I have enemy ships with predictive targeting. My player ship and enemy ships are kinematic, so in order to predict the future position of their targets, the need to access the current targets script to read the speed and turn rate.

My players main movement script is called shipControl
My enemy main movement script is called enemyAI

So, when an enemy is targeting the player I use

shipControl targetScript;

targetScript = targetObj.GetComponent<shipControl>();

targetSpeed = targetScript.shipSpeed;
targetTurn = targetScript.shipTurn;

This all works fine, but now what if I want my enemy ships to target each other? Their “enemyAI” scripts use the same variables shipSpeed and shipTurn, the idea being when they select a new target, they can simply use GetComponent to get a reference to the new targets script and then use targetScript.shipSpeed and targetScript.shipTurn info from it.

Because the player and enemies use different script names, I can’t just use targetScript = targetObj.GetComponent(); because targetScript is already cast to type shipControl.

Obviously I could just use targetSpeed = targetObj.GetComponent().shipSpeed, but for the sake of efficiency I want to be able to cache the reference to the current targets script rather than use GetComponent every frame.

So, is there a way I can reuse the same script component reference “targetScript” to access scripts with different names on the fly in c#? Am I missing something obvious?

I hope that’s all clear! Thanks :slight_smile:

Hi,

Possibly the simplest way to accomplish what you’d like is through inheritance.

eg:

public class Ship : MonoBehaviour
{
    public float shipSpeed;
    public float shipTurn;

    // etc
}

and then:

public class shipControl : Ship
{
// ...
}

public class enemyAI : Ship
{
// ...
}

Then instead of passing around or using shipControl and enemyAI classes rather cast to Ship after you call GetComponent

eg:

   Ship targetScript = targetObj.GetCompoonent<shipControl>() as Ship;
   //or
   Ship targetScript = targetObj.GetCompoonent<enemyAI>() as Ship;

Thanks for the quick reply DarkArts!

After posting I realised classes might be something to do with it. I’d yet to delve into classes and inheritance but I’m watching a tutorial on the topic right now.

Thanks for your help!

Well, I did manage to get this working, once I wrapped my head around it, but it just seems like a rather round-about way to do it.

I created a new script, TargetData, that inherits from MonoBehaviour…

using UnityEngine;
using System.Collections;

public class TargetData : MonoBehaviour
{
	public float shipSpeed;
	public Vector3 shipTurn;
}

I then made the whole class for enemyAI and shipControl inherit from TargetData and I’m able to use GetComponent in the way that you described.

TargetData targetScript = hit.transform.GetComponent<EnemyAI>() as TargetData;

As I say, it works just fine, but it just feels like having the bulk of my code inherit from that tiny little class above just for easy access to 2 variables can’t be the only way to go about it? o.O Is it a particularly unusual thing I’m trying to achieve? Or am I just worrying over nothing? :slight_smile:

I’ll continue looking into classes inheritance till it clicks a little more :slight_smile:

Thanks!

Strictly speaking it’s not “TargetData”. Perhaps if you think of it as “TargetableType”, or “Ship”

Where PlayerShip and EnemyShip are both a Ships (or TargetableTypes).

You could extend the TargetableType to have functions and methods that both PlayerShip and EnemyShip use, for example something like “raiseShields” etc.

The old example used for Classes and Inheritance is cars.

Where Ford is a car and Porche is a car. Both have a steering wheel, both have four wheels, both have a paint-job so add the wheels and steering wheel and paint-job in “Car”, from which Ford and Porche both inherit, it’s their blue-print which they can then modify themselves if required, but the basic shared elements need only be defined in one, shared place.

Awesome… that paragraph just caused a loud “CLICK!”

Thanks again, makes perfect sense now :slight_smile:

You can get the component this way:

class Ship: MonoBehaviour { }
class PlayerShip: Ship { }
class EnemyShip: Ship { }

...
var ship = hit.transform.GetComponent<Ship>();

Since both PlayerShip and EnemyShip are Ship, you can just look for the general Ship component.