1

I have a main code that stores all information about a player:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

[CreateAssetMenu(fileName = "CarData", menuName = "Data/Car/CarData")]
public class CarData : ScriptableObject
{
    [SerializeField] public ScriptableObject carAttachmentData;
    private int playerHealth;
    void Start()
    {
        playerHealth = carBodyData.health;
    }
}

and I need this variable to accept only two classes, namely these:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

[CreateAssetMenu(fileName = "CarAttachment1Data", menuName = "Data/Car/CarAttachmentData")]
public class CarAttachment1Data : ScriptableObject
{
    public int health; //for example
}

and

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

[CreateAssetMenu(fileName = "CarAttachment2Data", menuName = "Data/Car/CarBodyData")]
public class CarAttachment2Data : ScriptableObject
{
    public int health; //for example
}

and the unit gives an error when compiling:

'ScriptableObject' does not contain a definition for 'healthUp' and no accessible extension method 'healthUp' accepting a first argument of type 'ScriptableObject' could be found (are you missing a using directive or an assembly reference?)

(in reality, the healthUp variable exists, this is the real error code)

the problem can be solved by accepting the data CarAttachment1Data or CarAttachment2Data, but I need the variable to take two possible classes at once, since this option is allowed

classes cannot be combined, since in unity these are completely different objects, but they contain the same classes that are needed to get them in the main script

tried public interface but it generates an error

tried asking chatGPT question but it couldn't help

Retired Ninja
  • 4,785
  • 3
  • 25
  • 35
  • 1
    You can certainly have the field be of type `object`, but that means you have to check the type every time you use it. It would be a better design to have `CarAttachment1Data` and `CarAttachment2Data` derive from `CarData`, so the types are actually related. – Tim Roberts Feb 22 '23 at 02:11
  • Welcome to the world of Object Oriented Programming ;) As mentioned before you would use a common ancestor for such cases. The (generally better) alternative would be an `interface` but Unity can't really serialize those so Unity specific inheritance is most of the time the way to go – derHugo Feb 22 '23 at 07:44

1 Answers1

1

It is not possible to declare a variable of 2 different types in c#. You can move common functionality into a base class:

using UnityEngine;

public class CarBase : ScriptableObject
{
    public int Health;
}

subclasses:

using UnityEngine;  

[CreateAssetMenu(fileName = "Truck", menuName = "Truck", order = 0)]
public class Truck : CarBase
{
    public int LoadCapacity;
}

and

using UnityEngine;

[CreateAssetMenu(fileName = "Taxi", menuName = "Taxi", order = 0)]
public class Taxi : CarBase
{
    public int PassengersCount;
}

in Editor you can save 2 different assets for "Taxi" and "Truck" and check type in the calling code:

using UnityEngine;

public class Garage : MonoBehaviour
{
    [SerializeField] private CarBase carInfo;

    public void Awake()
    {
        Debug.Log(carInfo.Health);
        if (carInfo is Taxi)
        {
            var taxiInfo = (Taxi)carInfo;
            Debug.Log(taxiInfo.PassengersCount);
        }
    }
}
stazik
  • 174
  • 1
  • 1
  • 9