Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Question Created a Scriptable Object but don't understand how to access the data within

Discussion in 'Scripting' started by Xerun1, Sep 12, 2023.

  1. Xerun1

    Xerun1

    Joined:
    Sep 9, 2022
    Posts:
    15
    https://imgur.com/a/7LK1LYH

    I have created the attached image in a Scriptable Object. But I am having trouble actually accessing the data.


    Ideally, I'd like to input the phase number and then select from the attacks possible and pull the data. But I can't even seem to access the data, it just appears as Enemy_Attacks + Attacks[]
    Code (CSharp):
    1. public void Check_Attacks()
    2. {
    3.     foreach(Num_Attacks A in Enemy_AI.Number_Phases)
    4.     {Debug.Log(A.Number_Attacks);
    5.  
    6.     }
    7. }


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEditor;
    4. using UnityEngine;
    5.  
    6.  
    7. [CreateAssetMenu(fileName = "Attacks", menuName = "Attacks/Enemy_Attacks", order = 0)]
    8. public class Enemy_Attacks : ScriptableObject {
    9.     [SerializeField] public Enemy_Phases Enemy_AI;
    10.     [SerializeField] CharacterClass[] Character_Type = null;
    11.  
    12.     [System.Serializable]
    13.     public class Num_Attacks
    14.     {
    15.         public Attacks[] Number_Attacks;
    16.     }
    17.  
    18.     [System.Serializable]
    19.     public class Attacks
    20.     {
    21.         public Attack_Types Type;
    22.         public string Attack_Name;
    23.         public float XRange;
    24.         public float ZRange;
    25.         public float Offset;
    26.         public float Attack_Weights;
    27.     }
    28.  
    29.  
    30. [System.Serializable]
    31.     class CharacterClass
    32.     {
    33.         [SerializeField] public EnemyClassType ClassTypeAssigned;
    34.         public EnemyStatDictionarySpecific[] stats;
    35.    
    36.     }
    37.  
    38. [System.Serializable]
    39.     public class Enemy_Phases
    40.     {
    41.         public Num_Attacks[] Number_Phases;
    42.    
    43.     }
    44.     [System.Serializable]
    45.     class EnemyStatDictionarySpecific
    46.     {
    47.         public EStatsEnum EnemySpecificStat;
    48.         public float[] EnemyLevels;
    49.  
    50.     }
    51.  
     
    Last edited: Sep 12, 2023
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,251
    You seem to have nested all these classes, so they will all need to be written as
    Enemy_Attacks.Num_Attacks
    for example. If they're intended primarily to be used outside this type, then put them all into their own script assets. This is standard best practice anyway.

    Your code doesn't really make sense. First you need a reference to an instance of this
    Enemy_Attacks
    scriptable object.Then, you can acces the
    Enemy_AI
    array in whatever way suits you.

    Same with everything else. So you need to first get an instance of an element in the array, then just access its internal array.

    For example:
    Code (CSharp):
    1. public class SomeMonobehaviour : Monobehaviour
    2. {
    3.     [SerializeField]
    4.     private Enemy_Attacks _enemyAttacks;
    5.    
    6.     private void Start()
    7.     {
    8.         foreach(Enemy_Phase phase in _enemyAttacks.Enemy_AI)
    9.         {
    10.             foreach(Num_Attacks numAttacks in phase.Number_Phases)
    11.             {
    12.                 foreach (Attacks attack in numAttacks.Number_Attacks)
    13.                 {
    14.                     Debug.Log(attack.Type);
    15.                 }
    16.             }
    17.         }
    18.     }
    19. }
    Mind you you most of these fields should be private, and either have read-only properties, or have methods for accessing them. Collections in general should not be exposed publically.
     
    SisusCo and Xerun1 like this.
  3. Xerun1

    Xerun1

    Joined:
    Sep 9, 2022
    Posts:
    15
    OK that's not going to work how I intend then. What I want to do is create an integer value called Phases that can be dynamically changed per enemy. Then within each phase I want to put the attacks with each of their different variables.

    So then within my Enemy AI script I can call each attack that is present in the phase.

    is there a way to do this with a scripted object? I thought this was the best way but the above won't really cut it since Enemy_Phase and Num_Attacks I was hoping would work as integers
     
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,251
    You can still access elements of these arrays via indexes, I just wrote an example that iterated through them. So it probably can work as necessary. Or you may need a more robust means of extracting what you need.

    Mind you the question isn't really about scriptable objects, this is just a regular C# affair. Scriptable objects are just objects you can create as assets. Otherwise, when dealing with them, normal C# rules apply.
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    37,265
    Make two buckets in your mind:

    - immutable things that you author beforehand, such as "broadsword attacks for 6 pts"

    - mutable things that change at runtime "broadsword worn out attacks for 4 pts"

    Now that you have those two buckets...

    ScriptableObjects are what you use for the first.

    This is because they map 1-to-1 with what is on disk.

    For part 2, just use regular classes (or MonoBehaviours if you insist) to store that data.

    Whatever you do, start simple and build up THOUGHTFULLY, or else you will get lost in a confusing morass.

    ScriptableObject usage in RPGs:

    https://forum.unity.com/threads/scr...tiple-units-in-your-team.925409/#post-6055289

    https://forum.unity.com/threads/cre...ssigned-in-the-inspector.946240/#post-6174205

    Usage as a shared common data container:

     
    spiney199 likes this.
  6. Xerun1

    Xerun1

    Joined:
    Sep 9, 2022
    Posts:
    15

    Ok. Yep I get it.

    I thought it would be a simple way to create all enemy attacks. But it’s not as simple as I hoped.