Unsafe code with Unity

Does Unity compile unsafe code. The reason I am asking is not for performance issues. I’m trying to implement something similar to AngryAnts CopyInspector but work on single values instead of all the properties which is looking in possible at the moment. I can’t do reference comparisons because int float double ect get boxed. The only way I can see a way of doing what I want is to do pointer comparisons. I know this is unsafe but the memory locations should be the same at the point of comparison.

Edit: Thought I may aswell post my code. Its nothing special. The SaveValue methods are where I’m trying to implement my saving functionality.

CompoundGUIElement

/// <summary>
/// Base Class for CompoundGUIElements
/// </summary>
/// <typeparam name="T"></typeparam>
[System.Serializable]
public class CompoundGUIElement<T> : DraggableElement
{
    #region ENUMS

    /// <summary>
    /// enum for specifying placement of GUI Elements within a CompoundGUIElement
    /// </summary>
    public enum CompoundGUIPlacement
    {
        Top,
        Bottom,
        Left,
        Right
    }
    
    #endregion

    #region PRIVATE MEMBERS

    private T _initialValue;
    private T _tempValue;
    private T _value;
    private Boolean _showSetButton;
    private Boolean _showResetButton;
    private CompoundGUIPlacement _setButtonPlacement = CompoundGUIPlacement.Left;
    private CompoundGUIPlacement _resetButtonPlacement = CompoundGUIPlacement.Left;
    private Boolean _setIsAppending = false;
    private Boolean _saveIsAppending = false;
    private Color NORMAL_TINT_COLOR = Color.white;
    private Color SET_APPENDING_TINT_COLOR = Color.red;
    private Color SAVE_APPENDING_TINT_COLOR = Color.green;

    #region DRAGGABLE ELEMENT ATTRIBUTE IMPLEMENTATIONS

    private Rect _dragRect;
    private Dictionary<string, System.Object> _objectReferences;

    #endregion

    #endregion

    #region PROPERTIES
    /// <summary>
    /// The value defined for the Element upon Initialization.
    /// </summary>
    public T InitialValue { get { return _initialValue; } }
    /// <summary>
    /// The value of the object before it is Set.
    /// </summary>
    public T TempValue { get { return _tempValue; } }
    /// <summary>
    /// The definate value of the Element.
    /// </summary>
    public T Value { get { return _value; } }
    /// <summary>
    /// Defines whether the set button should be displayed. The value can still be 
    /// set by using the return key when the Element is in focus.
    /// </summary>
    public Boolean ShowSetButton { get { return _showSetButton; } set { _showSetButton = value; } }
    /// <summary>
    /// Defines whether the Reset Button should be displayed.
    /// </summary>
    public Boolean ShowResetButton { get { return _showResetButton; } set { _showResetButton = value; } } 
    /// <summary>
    /// Defines the placement of the Set Button. Use CompoundGUIPlacement instead of a 
    /// string for constistency.
    /// </summary>
    public CompoundGUIPlacement SetButtonPlacement { get { return _setButtonPlacement; } set { _setButtonPlacement = value; } }
    /// <summary>
    /// Defines the placement of the Reset Button. Use CompoundGUIPlacement instead of a
    /// string for consistency.
    /// </summary>
    public CompoundGUIPlacement ResetButtonPlacement { get { return _resetButtonPlacement; } set { _resetButtonPlacement = value; } }
    /// <summary>
    /// Defines whether the Elements value is awaiting the user to set the value.
    /// </summary>
    public Boolean SetIsAppending { get { return _setIsAppending; } }

    #region DRAGGABLE ELEMENT PROPERTY IMPLEMENTATIONS
    /// <summary>
    /// The Rectangle that defines where the Element responds to 
    /// Drag Events from the input device.
    /// </summary>
    public Rect DragRect 
    {
        get { return _dragRect; }
        set { _dragRect = value; } 
    }
    /// <summary>
    /// The array of object references that are being dragged. 
    /// </summary>
    public Dictionary<string, System.Object> ObjectReferences
    {
        get { return _objectReferences; }
        set { _objectReferences = value; }
    }

    #endregion

    #endregion

    #region DELEGATES & EVENTS
    /// <summary>
    /// Delegate Signature for CompoundGUI Events.
    /// </summary>
    /// <param name="e"></param>
    public delegate void CompoundGUIEventDelegate(CompoundGUIEventArgs e);
    /// <summary>
    /// The event called when the Element Value is Set.
    /// </summary>
    public event CompoundGUIEventDelegate OnSetEventHandler;
    /// <summary>
    /// The event call when the Element Value is Reset.
    /// </summary>
    public event CompoundGUIEventDelegate OnResetEventHandler;
    /// <summary>
    /// The event called when the Element Value is Reverted back to the TempValue.
    /// </summary>
    public event CompoundGUIEventDelegate OnRevertEventHandler;

    #endregion

    #region INITIALIZATION
    /// <summary>
    /// Initializes the CompoundGUIElement. Should be called after instantiation or in Awake.
    /// </summary>
    /// <param name="value"></param>
    public void Init(T value)
    {
        Init(value, true, CompoundGUIPlacement.Left);
    }
    /// <summary>
    /// Initializes the CompoundGUIElement. Should be called after instantiation or in Awake.
    /// </summary>
    /// <param name="value"></param>
    /// <param name="showSetButton"></param>
    public void Init(T value, Boolean showSetButton)
    {
        Init(value, showSetButton, CompoundGUIPlacement.Left);
    }
    /// <summary>
    /// Initializes the CompoundGUIElement. Should be called after instantiation or in Awake.
    /// </summary>
    /// <param name="value"></param>
    /// <param name="setButtonPlacement"></param>
    public void Init(T value, CompoundGUIPlacement setButtonPlacement)
    {
        Init(value, true, setButtonPlacement);
    }
    /// <summary>
    /// Initializes the CompoundGUIElement. Should be called after instantiation or in Awake.
    /// </summary>
    /// <param name="value"></param>
    /// <param name="showSetButton"></param>
    /// <param name="setButtonPlacement"></param>
    public void Init(T value, Boolean showSetButton, CompoundGUIPlacement setButtonPlacement)
    {
        _initialValue = value;
        _setButtonPlacement = setButtonPlacement;
        _showSetButton = showSetButton;

        _tempValue = value;
    }

    #endregion

    #region CUSTOM METHODS
    protected bool CheckValueChanged()
    {
        return !Equals(_tempValue, _value);
    }
    
    /// <summary>
    /// Sets and stores the Value stored in TempValue.
    /// </summary>
    protected virtual void SetValue()
    {
        _value = _tempValue;
        _setIsAppending = false;
        if (OnSetEventHandler != null)
            OnSetEventHandler(new CompoundGUIEventArgs());
    }
    /// <summary>
    /// Sets the Temp Value by using regular Unity GUI calls. This must be called within
    /// OnGUI
    /// </summary>
    public void DrawGUI()
    {   
        if (CheckValueChanged() == true)
        {
            _setIsAppending = true;
        }
        
        //create gui elements here
        switch (_setButtonPlacement)
        {
            case CompoundGUIPlacement.Top:
                {
                    GUILayout.BeginVertical("Toolbar", GUILayout.ExpandWidth(true));
                    DrawResetButton();
                    DrawSetButton();
                    DrawCustomGUI();
                    if (EditorApplication.isPlaying)
                        DrawSaveButton();
                    GUILayout.EndVertical();
                    break;
                }
            case CompoundGUIPlacement.Bottom:
                {
                    GUILayout.BeginVertical("Toolbar", GUILayout.ExpandWidth(true));
                    DrawCustomGUI();
                    DrawResetButton();
                    DrawSetButton();
                    if (EditorApplication.isPlaying)
                        DrawSaveButton();
                    GUILayout.EndVertical();
                    break;
                }
            case CompoundGUIPlacement.Left:
                {
                    GUILayout.BeginHorizontal("Toolbar", GUILayout.ExpandWidth(true));
                    DrawResetButton();
                    DrawSetButton();
                    if (EditorApplication.isPlaying)
                        DrawSaveButton();
                    DrawCustomGUI();
                    GUILayout.EndHorizontal();
                    break;
                }
            case CompoundGUIPlacement.Right:
                {
                    GUILayout.BeginHorizontal("Toolbar", GUILayout.ExpandWidth(true));
                    DrawCustomGUI();
                    DrawResetButton();
                    DrawSetButton();
                    if (EditorApplication.isPlaying)
                        DrawSaveButton();
                    GUILayout.EndHorizontal();
                    break;
                }
        }
    }
    /// <summary>
    /// Draws the custom elements for the Compound Element. Override and Implement 
    /// Custom GUI calls to create your own Compound Elements
    /// </summary>
    protected virtual void DrawCustomGUI()
    {

    }
    /// <summary>
    /// Draws the Set Button. Override this method to implement your own Set Button or Element.
    /// </summary>
    protected virtual void DrawSetButton()
    {
        if (_setIsAppending == true)
        {
            //GUI.backgroundColor = SET_APPENDING_TINT_COLOR;
            GUI.contentColor = SET_APPENDING_TINT_COLOR;
        }

        if (GUILayout.Button("Set", "ToolbarButton", GUILayout.Width(50.0f), GUILayout.ExpandWidth(false)))
            SetValue();

        //GUI.backgroundColor = NORMAL_TINT_COLOR;
        GUI.contentColor = NORMAL_TINT_COLOR;
    }
    /// <summary>
    /// Draws the Reset Button. Override this method to implement your own Reset Button or Element.
    /// </summary>
    protected virtual void DrawResetButton()
    {
        
        if (GUILayout.Button("Reset", "ToolbarButton", GUILayout.Width(50.0f), GUILayout.ExpandWidth(false)))
            ResetValue();

    }
    /// <summary>
    /// Draws the Save Button. Override this method to implement your own Reset Button or Element.
    /// </summary>
    protected virtual void DrawSaveButton()
    {
        if (_saveIsAppending)
            GUI.contentColor = SAVE_APPENDING_TINT_COLOR;


        if (GUILayout.Button("Save", "ToolbarButton", GUILayout.Width(50.0f), GUILayout.ExpandWidth(false)))
            SaveValue();

        GUI.contentColor = NORMAL_TINT_COLOR;
    }
    /// <summary>
    /// Resets the Elements Value to its initial value.
    /// </summary>
    protected virtual void ResetValue()
    {
        _value = _initialValue;
        _tempValue = _initialValue;
        _setIsAppending = false;
        if(OnResetEventHandler != null)
            OnResetEventHandler(new CompoundGUIEventArgs());
    }
    /// <summary>
    /// Saves the Elements Value so it isn't reverted when exiting playmode.
    /// </summary>
    protected virtual void SaveValue()
    {
        _saveIsAppending = !_saveIsAppending;

        //**TODO** Call CompoundDataManager.SaveValue() to save the value
    }
    /// <summary>
    /// Sets the Element so that a Set is not appending.
    /// </summary>
    protected virtual void RevertValue()
    {
        _setIsAppending = false;
    }

    #endregion

    #region DRAGGABLE ELEMENT METHOD IMPLEMENTATIONS
    /// <summary>
    /// Starts the drag Event
    /// </summary>
    public virtual void StartDrag()
    {

    }
    /// <summary>
    /// Called during a drag event
    /// </summary>
    public virtual void Drag()
    {

    }
    /// <summary>
    /// Called when a drag event ends
    /// </summary>
    public virtual void EndDrag()
    {

    }
    /// <summary>
    /// Adds a a reference to an Object for dragging.
    /// </summary>
    /// <param name="identifier">The string to identify the Object Reference</param>
    /// <param name="objectReference">The Object Reference for storing</param>
    /// <returns>System.Object</returns>
    System.Object DraggableElement.AddObjectReference(string identifier, System.Object objectReference)
    {
        _objectReferences.Add(identifier, objectReference);
        return _objectReferences[identifier];
    }
    /// <summary>
    /// Removes an Object from being a draggable reference.
    /// </summary>
    /// <param name="identifier">The string that identifies the Object Reference that will be removed</param>
    /// <returns>System.Object</returns>
    System.Object DraggableElement.RemoveObjectReference(string identifier)
    {
        _objectReferences.Remove(identifier);
        return _objectReferences[identifier];
    }
    /// <summary>
    /// Removes all the draggable Object References.
    /// </summary>
    /// <returns>List of System.Objects</returns>
    List<System.Object> DraggableElement.RemoveAllObjectReferences()
    {
        List<System.Object> objectRefs = new List<System.Object>(_objectReferences.Count);
        foreach(KeyValuePair<string, System.Object> pair in _objectReferences)
        {
            objectRefs.Add(pair.Value);
        }

        _objectReferences.Clear();
        return objectRefs;
    }

    #endregion
}

CompoundTextField

/// <summary>
/// Compound TextField
/// </summary>
class CompoundTextField:CompoundGUIElement<string>
{
    protected override void DrawCustomGUI()
    {
        _tempValue = GUILayout.TextField(_tempValue, "ToolbarTextField", GUILayout.ExpandWidth(true));
    }
}

CompoundDataManager

public static class CompoundDataManager
{
    //Dictionary of some sort, here, to store values. Will use instanceID as primary key
    
    /// <summary>
    /// Saves the value from the passed in component
    /// </summary>
    /// <param name="component"></param>
    /// <param name="value"></param>
    public void SaveValue(Component component, System.Object value)
    {
        //**TODO** Find Solution for comparing value references
    }
    /// <summary>
    /// Sets the saved values when exiting playmode
    /// </summary>
    /// <param name="component"></param>
    public void SetValues(Component component)
    {

    }
}

I'm still not sure what you want to achieve, but unsafe code won't work in Unity.

Actually it sounds like you don't need unsafe code but simple reflection...

With reflection you can process all properties / fields / what ever. There are only some problems you can bump into: If you read some of the properties of unity-objects like Renderer.material you will get a mem-leak with warning because you should not use .materials in the editor. only sharedMaterial can / should be accessed. There are several special cases you have to take case about. Beside that you should be able to “analyse” every component / class.

Can you explain your actual problem a bit more in detail? int, float, double... are value types so i don't get your reference comparison. For what reason do you want to compare what values / references?