Setting a property, and then making it readonly. (c#)

Hello there, I’m attempting to make an ability/spell system for my game project. The Abilities utilize interfaces for common characteristics, while providing more custom functionality on their own.

So far, this works great. However; as this is meant to be a multiplayer game, I’m thinking that much of the information is too open, and would like to limit it’s access as much as possible.

On a step down this road, I was thinking that the properties inherited from my interfaces should be readonly when possible. Sadly, I’m not sure how to do this and still set the property within the Ability itself.

Here is the current baselevel interface, IAbility.

using UnityEngine;

interface IAbility
{
	int ID {get;set;}	              //Identification
	string Name {get;set;}	          //Ability Name
	string Description {get;set;}	  //Description
	float Cost {get;set;}		      //Energy Cost	
	GameObject Effect {get;set;}	  //Particle Effect	
	bool LineOfSight {get;set;}  	  //Require LOS?
	float BaseCooldownTime {get;set;} //Default Cooldown
	float CastTime {get;set;}         //Time to cast	
	
	void Cast();
}

And here is an example of a spell, with the custom functionality left out.

using UnityEngine;
using System.Collections;

public class Fireball : MonoBehaviour, IAbility
{
	#region IAbility implementation
	
	public int ID {get;set;}
	public string Name  {get;set;}
	public string Description  {get;set;}
	public float Cost  {get;set;}
	public GameObject Effect  {get;set;}
	public bool LineOfSight  {get;set;}
	public float BaseCooldownTime  {get;set;}
	public float CastTime {get;set;}	
	
	#endregion
	

	Fireball ()
	{
		ID = 0;
		Name = "Fireball";
		Description = "Hurl a molten core towards your foe.";
		Cost = 15;							                               
		Effect = fireballEffect;     //Prefab set later in script	                        
		LineOfSight = false;				
		BaseCooldownTime = 2.0f;
		CastTime = 1.5f;	
	}
	
	public Cast ()
	{
	  //Spell's functionality
	}

Finally, here is an example of the kind of script (on the player) that will handle actually casting the spell. It is still in test form. I have decided to do many of the common ability functions on this side, to save code.

using UnityEngine;
using System.Collections;

public class Caster : MonoBehaviour 
{

	IAbility ability1;
	float ability1Timer;

	PlayerEnergy energyScript;

	// Use this for initialization
	void Start () 
	{
		energyScript = GetComponent<PlayerEnergy>();

		ability1 = GetComponent<Fireball>();        //This will be done by playerPrefs in the future.
		ability1Timer = 0;

	}
	
	// Update is called once per frame
	void Update () 
	{
		if(Input.GetButtonDown("Fire1")
		   && Screen.lockCursor == true
		   && energyScript.energy >= ability1.Cost
		   && Time.time >= ability1Timer)
		{
			energyScript.energy -= ability1.Cost;
			ability1Timer = Time.time + ability1.BaseCooldownTime;
			ability1.Cast();
		}
	}
}

I’m still quite new to Unity and programming in general, so I’m sure all of this is inelegant and not very secure. To reiterate, this works, but I’m looking for advice on how to make it more secure, and efficient. Particularly in regards to the inherited properties and how to make them readonly after the ability sets them.

If you took the time to read through all of that, thank you. If there is anything I can do to make this more complete, please let me know.

I’m not sure I understand 100% what you’re trying to do, but if you want to make a property that is read-only after the first time that it has been set, you can use the following C# code:

class SomeClass : MonoBehaviour {
    private SomeObj _obj = null;
    public SomeObj Obj {
        get {return _obj;}
        set {
            if (_obj == null) {
                _obj = value;
            }
        }
    }
}

So what we have here, is a property name Obj, that starts as null, and can always be read. But when trying to set it’s value, it will only set it if it’s null. Once it’s been set, you cannot set it again, because it is no longer null.

.net - Is there a way of setting a property once only in C# - Stack Overflow - this question contains WriteOnly and other generic examples, that can be useful for setting once