wander, stop, and look at target, wander again [not all code paths return a value]...

I’m new to programming, so excuse my ignorance on what is probably a mish-mash of code. I Have done a lot of searching through questions etc. And haven’t been able to find an answer.

I’m trying to make game characters wander, stop & turn to look at target, then start wandering again by modifying [this][1] unity script.

So far I can’t seem to get it to work…

Currently, Unity is telling me: Unexpected symbol `PictureTransforms’ (in the else statement in the update method).

Is it because I’m trying to put a method inside a method?

Any help I could get on this would be hugely appreciated.

My Code is Below:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

[RequireComponent(typeof(CharacterController))]
public class Wander : MonoBehaviour
{
	public float speed = 5;
	public float directionChangeInterval = 3;
	public float maxHeadingChange = 75;
	public List<Transform> PictureTransforms;
	CharacterController controller;
	float heading;
	Vector3 targetRotation;

	void Awake ()
	{
		controller = GetComponent<CharacterController>();
 
		// Set random initial rotation
		heading = Random.Range(0, 360);
		transform.eulerAngles = new Vector3(0, heading, 0);
 
		StartCoroutine(NewHeading());
	}
	void Start()
	{
		foreach(GameObject picture in GameObject.FindGameObjectsWithTag("Picture")) {
 
             PictureTransforms.Add(picture.transform);
         }
	}
 
 	Transform FindClosestEnemy(List<Transform> PictureTransforms){
		Transform bestTarget = null;
		float closestDistanceSqr = Mathf.Infinity;
		Vector3 currentPosition = transform.position;
		foreach (Transform potentialTarget in PictureTransforms)
		{
		Vector3 directionToTarget = potentialTarget.position - currentPosition;
		float dSqrToTarget = directionToTarget.sqrMagnitude;
		if (dSqrToTarget < closestDistanceSqr)
		{
		closestDistanceSqr = dSqrToTarget;
		bestTarget = potentialTarget;
		}
		return bestTarget;
		}
		}
	void Update ()
	{
		

		if (speed > 0){
		transform.eulerAngles = Vector3.Slerp(transform.eulerAngles, targetRotation, Time.deltaTime * directionChangeInterval);
		} else {
			transform.LookAt(FindClosestEnemy(List<Transform> PictureTransforms).position, Vector3.up);
		}
		var forward = transform.TransformDirection(Vector3.forward);
	
		controller.SimpleMove(forward * speed);
	}
	
 
	IEnumerator NewHeading ()
	{
		while (true) {
			NewHeadingRoutine();
			yield return new WaitForSeconds(directionChangeInterval);
		}
	}
 
	void NewHeadingRoutine ()
	{
		var floor = Mathf.Clamp(heading - maxHeadingChange, 0, 360);
		var ceil  = Mathf.Clamp(heading + maxHeadingChange, 0, 360);
		heading = Random.Range(floor, ceil);
		targetRotation = new Vector3(0, heading, 0);
	}
}

NOTE: I haven’t put in a method to change speed at different intervals yet, as I’m just experimenting by changing the speed value in the inspector during runtime at the moment.

You um, are trying to declare a list instead of using one.

The code paths? In a non void Function, i.e. one that needs a return if you have branching statements (if else etc) that can cause a variation in the flow of code, you must make sure that each possible code path flow terminated with a return suitable for the Function. I dont know for sure but maybe returning null for a Transform might break it.

Hi,

  • Do you have a class/script in your project called “PictureTransforms” (with a capital P) ? It might be the formatting of Unity Answers but the fact that your variable is tinted in pink seems odd to me (plus, all your other variables have non capital first letters but non this one).

  • As meat5000 said, when your method returns a type, you must be sure that the function reaches a “return” sometime. If the compiler finds a way to not reach a “return”, it will prompt the “not all paths return a value” error. Even if you manage to never create the situation at runtime.

  • In the FindClosestEnemy mehtod, your only “return” is in a foreach loop. If the list that goes in the foreach is null or empty, the loop will be skipped and thus not “return” is reachable. You should try something like this:

    if(my list has more than 0 element OR is not null)
    {
    foreach(Transform potentialTarget in PictureTransforms)
    {
    // Do your stuff
    }
    }

  • You could also just input your “return bestTarget” outside the foreach loop. This way, the method will return a null value (or whatever value you set when creating your bestTarget variable) unless the list given in argument of the method is not null/empty and changes the bestTarget value between the creation and the return.

Hope this helps
Cheers

Waylander