- Home /
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.
Just remove in Update()
the List<Transform>
from before PictureTransforms
, and that issue will be solved (once you declare the type of a variable, you don't use it anymore, just the name).
Try the suggestions of $$anonymous$$dRWaylander, they should get you on track.
Answer by KdRWaylander · Mar 12, 2018 at 09:44 AM
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
Answer by meat5000 · Mar 12, 2018 at 03:16 AM
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.
You can return a null Transform. The problem is that the return statement is within the foreach (difficult to see due to lack of formatting), so if PictureTransforms is empty, there will be no return operation, which the compiler correctly detects.
Change the order of the of return bestTarget
and the penultimate }
to fix this specific error.
Indeed. I've never encountered a situation where I stuffed null across a return. They say you learn more getting it wrong then you do being right all the time :) It shows here
Your answer
Follow this Question
Related Questions
NPC code, works great, besides them being in the ground. 2 Answers
my prefab is null woe 2 Answers
How to store direction so that player faces last direction when joystick is idle 2 Answers
How to align & rotate objects to each other at run time? 1 Answer
Frame drop due to Physic2D.SyncColliderTransformChanges in profiler 1 Answer