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.
  2. Dismiss Notice

Accessing ScriptableObject data of current gameObject

Discussion in 'Scripting' started by Gegenton, Nov 6, 2019.

  1. Gegenton

    Gegenton

    Joined:
    Nov 4, 2019
    Posts:
    9
    Hi forum,

    i spent about 5h trying to figure out how to access variables of a ScriptableObject by addressing the current gameObject that this very SO is sitting on.

    Short idea of what I want to do:
    I created a SO
    RNode
    (researchNode) that will store information about inventions and the like. They will be represented by card-like looking game objects. I created a UI prefab that also holds
    RNodeDisplay.cs
    which basically just makes the text fields on the prefab using the given SO data.

    Now I want to drag the card from a starting position (will be something like a "hand" or "inventory" later on) to a position that it is designated to. I therefore created two zones called "Stoneage" and "Modern". The
    string type
    of the SO asset variable will hold the very same information for each asset.

    I only want to allow the node to be placed on the zone that matches the type it has.

    The problem: I can't figure out how to access the current gameObjects (the node that is being dragged around) type string, because I can't inherit, evoke, instantiate and what not the link to the information the SO asset holds.

    Because I'm at a point now where I (as a newbie) am so confused about how scripts and SOs and GOs etc. talk to each other... I'm here.

    The error message is:
    "ArgumentException: GetComponent requires that the requested component 'RNode' derives from MonoBehaviour or Component or is an interface.
    UnityEngine.Component.GetComponent[T] ()"

    I understand the difference between MonoBehaviour and SO, I also tried to work with transform, but just can't get it to work.


    Please find the four related codes here:

    SO
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [CreateAssetMenu(fileName = "New rNode", menuName ="New Nodes/Reasearch Node")]
    6. public class RNode : ScriptableObject
    7. {
    8.     public int ID;              // unique ID
    9.     public int parentID;        // the ID that this node is attached to
    10.     public string newName;      // name of the node
    11.  
    12.     public Sprite typeImage;    // image that shows the type of node, may later be replaced by prefab allocation?
    13.  
    14.     public string description;  // description
    15.     public string type;         // type of node, may later be changed to a list/array
    16.     public string timeAge;      // the time age that this node belongs to, may only be one
    17.  
    18.     public int rCost;           // reasearch costs in points
    19.     public int rTime;           // time it takes to research in minutes
    20.     public int gCost;           // gold costs in points
    21.  
    22.     public string effect;       // explanation of the effect
    23.     public float effectValue;   // effect value, e. g. 1,1 or -1,5 (later maybe two effects, one positive, one negative)
    24.  
    25.     public bool milestone;      // is this node a milestone or not?
    26.     public float rarity;        // rarity to find this node ranging from 0,01 to 1
    27.  
    28.     public string enabledB;     // the building enabled by this node
    29.     public string enabledW;     // the war item enabled by this node
    30.     public string enabledR;     // the research node enabled by this node (must not be a child)
    31.  
    32.     public string tags;         // tags for tags sake
    33.  
    34. }
    35.  


    Text display on UI
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class RNodeDisplay : MonoBehaviour
    7. {
    8.     // receive all rNode variables that are visible
    9.     public RNode rNode;
    10.  
    11.     public Text nameText;
    12.     public Image typeImage;
    13.     public Text descriptionText;
    14.     public Text effectText;
    15.     public Text enabledText;
    16.  
    17.     public Text rCostText;
    18.     public Text gCostText;
    19.  
    20.  
    21.    // enable allocation of UI elements to assets data
    22.     void Start()
    23.     {
    24.         nameText.text = rNode.newName;
    25.         typeImage.sprite = rNode.typeImage;
    26.  
    27.         descriptionText.text = rNode.description;
    28.  
    29.         effectText.text = rNode.effect;
    30.         enabledText.text = rNode.enabledB + rNode.enabledW + rNode.enabledR;
    31.  
    32.         rCostText.text = rNode.rCost.ToString();
    33.         gCostText.text = rNode.gCost.ToString();
    34.     }
    35. }
    36.  


    Dropzone
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.EventSystems;
    5.  
    6.  
    7. public class Dropzone : MonoBehaviour, IDropHandler
    8. {
    9.  
    10.     public void OnDrop(PointerEventData eventData)
    11.     {
    12.  
    13.         Draggable d = eventData.pointerDrag.GetComponent<Draggable>();  // receive data based on the position of the mouse (hovering an area)
    14.  
    15.         if (d != null)  // will most likely never be != null
    16.         {
    17.             d.parentToReturnTo = this.transform;    // receive information about the area and set the area to return to to the current one
    18.             Debug.Log("This is area" + this.name);
    19.         }
    20.  
    21.     }
    22. }


    Dragging operations
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.EventSystems;
    5.  
    6. public class Draggable : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
    7. {
    8.     public RNode rNode;     // does this import the currently dragged nodes rNode information?
    9.  
    10.     public Transform parentToReturnTo = null;       // variable that saves the last valid slot position
    11.      public void OnBeginDrag(PointerEventData eventData)
    12.     {
    13.         parentToReturnTo = this.transform.parent;       // the place the node starts being dragged is the "home" position
    14.         this.transform.SetParent(this.transform.parent.parent);
    15.         Debug.Log ("We begin dragin'");
    16.  
    17.         GetComponent<CanvasGroup>().blocksRaycasts = false;
    18.     }
    19.  
    20.     public void OnDrag(PointerEventData eventData)  // not actively used atm
    21.     {
    22.         this.transform.position = eventData.position;
    23.     }
    24.    
    25.     public void OnEndDrag(PointerEventData eventData)
    26.     {
    27.         this.transform.SetParent(parentToReturnTo);     // sets location that the node is on to new slot, will be enhanced by if statement checking the correct position
    28.         GetComponent<CanvasGroup>().blocksRaycasts = true;
    29.  
    30.         rNode = this.GetComponent<RNode>();     // this is where it get's messy. I can't access the component rNode from the current node
    31.         Debug.Log("And this is" + rNode.timeAge);   // prompts error
    32.  
    33.         Debug.Log(gameObject.name + " dragged on " + this.transform.parent.name);   // this debug at least shows me that the current gameObject is actually the node, not the UI zone
    34.     }
    35.  
    36. }
    37.  


    I've read documentations, tutorials, watched tutorials on inventory systems (because these have somewhat comparable actions going on). But I can't seem to find out the one thing that I'm missing.

    Thanks a lot in advance!



    Edit:
    I found out that if I drag the SO asset onto the editor's field for R Node, it works. I expected that. I need to find a way to exchange/reference this with the asset that is currently loaded by RNodeDisplay. I cannot "hard link" an asset to the Draggable script obviously. Arghhh...


    KR

    Gegenton
     
    Last edited: Nov 6, 2019
  2. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,833
    I'm pretty confused by your description, and I suspect that's because you are pretty confused about what you're doing.

    ScriptableObjects don't get attached to specific GameObjects in the way that MonoBehaviours do. You can't use GetComponent to get a ScriptableObject because there are, by definition, NO scriptable objects attached to the game object. Ever. It's unclear what you think this would do.

    Some of your scripts have
    public RNode rNode;
    . If that variable already contains a reference to the specific RNode you are interested in (perhaps assigned via the inspector), then to access that RNode you just use the variable. For instance, you could write "rNode.type".

    If you want to access the rNode variable on one component from another component, then you can use GetComponent to get the component that contains the variable, and then access the variable from there.

    If that variable doesn't already contain a reference to the appropriate RNode, then you need to figure out some way of specifying which RNode you are interested in.
     
  3. Gegenton

    Gegenton

    Joined:
    Nov 4, 2019
    Posts:
    9
    Hi Antistone,

    thanks for your quick reply!

    Sorry for being so misleading, yes I was confused. And I got even more confused by your answer because duhhh, that's exactly what I'm trying to do :D Anyway reading more carefully I got your point and added this to draggable.cs:


    RNodeDisplay z = gameObject.GetComponent<RNodeDisplay>();
    Debug.Log("And this is " + z.rNode.timeAge);


    Now it works. I think I simply needed to store the information in a variable first. Will dig deeper though, maybe I don't even need to temporarily store the "z" variable.


    Thanks again, seems to work for now..