Error on layerchange in cameraraycaster

rpg_s01_using_delegates_in_c

#1

I get this property or indexer cameraraycaster.layerhit can’t be assigned to (it’s read only). here is the code

using UnityEngine;

public class CameraRaycaster : MonoBehaviour
{
public Layer[] layerPriorities = {
Layer.Enemy,
Layer.Walkable
};

[SerializeField] float distanceToBackground = 100f;
Camera viewCamera;

RaycastHit m_hit;
public RaycastHit hit
{
    get { return m_hit; }
}

Layer m_layerHit;
public Layer layerHit
{
    get { return m_layerHit; }
}

public delegate void OnLayerChange(); // Declare delegate type
public OnLayerChange layerChangeObservers; // Instantiate observer set

	
void Start()
{
    viewCamera = Camera.main;
	layerChangeObservers (); // Call delegates
}

void Update()
{
    // Look for and return priority layer hit
    foreach (Layer layer in layerPriorities)
    {
        var hit = RaycastForLayer(layer);
        if (hit.HasValue)
        {
            m_hit = hit.Value;
			if (layerHit != layer) { //if layer changed
				layerHit = layer;
				layerChangeObservers(); //call delegates
			}
			m_layerHit = layer;
			return;
        }
    }

    // Otherwise return background hit
    m_hit.distance = distanceToBackground;
    m_layerHit = Layer.RaycastEndStop;
}

RaycastHit? RaycastForLayer(Layer layer)
{
    int layerMask = 1 << (int)layer; // See Unity docs for mask formation
    Ray ray = viewCamera.ScreenPointToRay(Input.mousePosition);

    RaycastHit hit; // used as an out parameter
    bool hasHit = Physics.Raycast(ray, out hit, distanceToBackground, layerMask);
    if (hasHit)
    {
        return hit;
    }
    return null;
}

}


#2
if (layerHit != layer) { //if layer changed
layerHit = layer;
layerChangeObservers(); //call delegates

layerHit is a property without a set statement.

you could add a setter to layerHit or
change it to

if (layerHit != layer) { //if layer changed
m_layerHit = layer;
layerChangeObservers(); //call delegates

Writing a setter would be the better solution.


#3

m_layerHit = layer is with the suggested solution inside the if statement and also outside it, one of them is not needed. In a later tidy up the ugly m_ are deleted anyway, leaving Ben’s code the layerHit = layer in the code twice, which is an unnecessary duplication, I deleted the one after the if code and everything works as intended.


#4

Look at your line in the foreach loop, nested in two if statements:

layerHit = layer; 

This is invalid, bad, sytax because your layerHit is a field with a getter defined, but no setter: rememeber what you wrong near the top of the class?:

public Layer layerHit
{
    get { return m_layerHit; }
}

To set this value, you should change the private variable m_layerHit instead.

So change that line I mentioned first to:

m_layerHit = layer; 

That will fix it.


ALTERNATIVELY, you could modify your field and add a setter, something like this would work:

public Layer layerHit
{
    get { return m_layerHit; }
    set {m_layerHit = value;}  // value is a magic keyword used by the compiler
}