[SOLVED] How to Assign A Sprite to a Private Variable?

I’m just wondering how to go about changing an object’s sprite at run-time without needing to clutter up the inspector with public variables. But I don’t know how to assign the sprite via code. I can do it with any other object type, just can’t figure it out for sprites.

Any help would be greatly appreciated!

- Chris

  1. you can hide public variables from the inspector with the ‘HideInInspector’ attribute:
[HideInInspector]
public Sprite someSprite;

Note you can also make private fields serializable and shown in the inspector with the ‘SerializeField’ attribute:

[SerializeField]
private Sprite _someSprite;
  1. you can create properties to uncover public access to private fields:
private Sprite _someUnserializedSprite;

public Sprite SomeSprite
{
    get { return _someUnserializedSprite; }
    set { _someUnserializedSprite = value; }
}

Note, the property also adds on a nice added bonus of allowing you to run code while updating the field. For example you can do some validation checking, call an event, or do any prep work that is required when swapping out values for that field in your class.

  1. and you can combine this all together to have a private field that is serialized, but also uses a property for access.
[SerializeField]
[Range(0f,1f)]
private float _percentage;

[SerializeField]
private UnityEvent _someEvent;

//note I validate the percentage passed in so that it is clamped.
//The 'Range' attribute restricts it in the inspector, the property restricts it at runtime.
public float Percentage
{
    get { return _percentage; }
    set { _percentage = Mathf.Clamp01(value); }
}

//note this property is effectively readonly,
//you can access the UnityEvent, manipulate it, but you can't set it.
public UnityEvent SomeEvent
{
    get { return _someEvent; }
}

Personally, because I come from a heavy .Net background where this is the preferred model of doing things, I make all fields private and flagged SerializeField. And if I need runtime access I make a public property for it:

using UnityEngine;
using UnityEngine.EventSystems;

using com.spacepuppy;
using com.spacepuppy.Scenario;
using com.spacepuppy.Tween;

namespace com.mansion.UI.Menus
{

    public class SelectionBorder : SPComponent
    {

        #region Fields
       
        [SerializeField]
        private float _easeDur = 1f;
        [SerializeField]
        EaseStyle _ease;
        [SerializeField]
        private bool _tweenSize;

        [SerializeField]
        private Trigger _onSelectionChanged;

        [System.NonSerialized]
        private GameObject _currentSelection;

        #endregion

        #region CONSTRUCTOR

        protected override void OnStartOrEnable()
        {
            base.OnStartOrEnable();

            _currentSelection = null;

            var ev = EventSystem.current;
            if (ev == null) return;
           
            this.SetCurrent(ev.currentSelectedGameObject, false, true);
        }

        #endregion

        #region Properties

        public float EaseDur
        {
            get { return _easeDur; }
            set { _easeDur = value; }
        }

        public EaseStyle Ease
        {
            get { return _ease; }
            set { _ease = value; }
        }

        public bool TweenSize
        {
            get { return _tweenSize; }
            set { _tweenSize = value; }
        }

        public GameObject CurrentSelection
        {
            get { return _currentSelection; }
        }

        public Trigger OnSelectionChanged
        {
            get { return _onSelectionChanged; }
        }

        #endregion

        #region Methods

        public void SetCurrent(GameObject go, bool animate = false, bool suppressOnChangeEvent = false)
        {
            if (go == null) return;
            if (_currentSelection == go) return;

            _currentSelection = go;
            if(animate)
            {
                var twn = SPTween.Tween(this.transform)
                 .To("position", _currentSelection.transform.position, _easeDur)
                 .Ease(EaseMethods.GetEase(_ease))
                 .UseRealTime();
                if (_tweenSize)
                {
                    var trans = _currentSelection.transform as RectTransform;
                    if (trans != null)
                    {
                        twn = twn.To("sizeDelta", trans.sizeDelta, _easeDur);
                    }
                }

                twn.Play(true, this);
            }
            else
            {
                this.transform.position = _currentSelection.transform.position;
                if (_tweenSize && this.transform is RectTransform)
                {
                    var trans = _currentSelection.transform as RectTransform;
                    if (trans != null)
                    {
                        (this.transform as RectTransform).sizeDelta = trans.sizeDelta;
                    }
                }
            }

            if (!suppressOnChangeEvent && _onSelectionChanged.Count > 0) _onSelectionChanged.ActivateTrigger(this, null);
        }

        #endregion

        #region Messages

        private void Update()
        {
            var ev = EventSystem.current;
            if (ev == null) return;
           
            var go = ev.currentSelectedGameObject;
            if (go == null) return;

            if (_currentSelection == go) return;

            this.SetCurrent(go, true, false);
        }

        #endregion

    }

}
2 Likes

Thanks a bunch for this! Very useful :slight_smile: