Unity Error CS0126 - c#

I'm sure it's something stupid simple, but I can't get it figured out. The following code:
public GameObject AISelectCannon() {
Debug.Log("AISelectCannon called");
GameObject desiredCannon = AIController.selectCannon(0);
if (desiredCannon.tag.Contains("Cannon")) return;
m_SelectedCannon = desiredCannon;
aiSelectionPending = true;
return m_SelectedCannon;
}
is throwing the following error:
Scripts/CubeContainer.cs(61,59): error CS0126: An object of a type convertible to `UnityEngine.GameObject' is required for the return statement
(GameObject desiredCannon.... is line 61)
Other relevant information from AIController:
public static GameObject selectCannon(int side) {
So yeah, any ideas?

Your first return statement isnt returning anything, it just says return
if (desiredCannon.tag.Contains("Cannon")) return // return something

Related

Why is the method returning in yield return get.SendWebRequest()

I have a function in unity that makes a request for a server, and for each value in the result, it should call a function to add a image on a list and get an object from the same server and add on another list
public void SaveServer() {
string serverAddress = inputField.text;
GlobalStateData.getInstance().ServerAdress = serverAddress;
StartCoroutine(Utils.GetRequest(GlobalStateData.getInstance().ServerAdress + "file/ObjectController/",
(UnityWebRequest) => {
JArray jsonResponse = JArray.Parse(UnityWebRequest.downloadHandler.text);
foreach (var json in jsonResponse) {
String base64 = (string)json["trackingImage"]["file"]["base64"];
String name = (string)json["file"]["name"];
int objectId = (int)json["id"];
Texture2D texture = Utils.Base64ToTexture2D(base64);
StartCoroutine(addImageAndObject(objectId, texture, name));
}
Debug.Log(jsonResponse);
transform.parent.Find("canvas_MainMenu").gameObject.SetActive(true);
gameObject.SetActive(false);
}));
}
private IEnumerator addImageAndObject(int objectId, Texture2D texture2D, String name) {
StartCoroutine(addImage(texture2D, name));
yield return AddObjectById(objectId, name).MoveNext();
}
but in the AddObjectById the method is stopping before complete the request
private IEnumerator AddObjectById(int id, string name) {
string url = GlobalStateData.getInstance().ServerAdress + "bundle/ObjectBundleController/" + id;
UnityWebRequest get = UnityWebRequest.Get(url);
yield return get.SendWebRequest(); // it stops here
if (get.result != UnityWebRequest.Result.Success) {
Debug.Log(get.error);
yield return false;
}
else {
AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(get);
GameObject obj = (GameObject)bundle.LoadAsset(name);
_place3DObjectRef.ArPrefabs.Add(obj);
yield return true;
}
}
I didn't understand how my GetRequest Method Works and the AddObjectById
Here is the GetRequest
public static IEnumerator GetRequest(string server, Action<UnityWebRequest> successCallback, Action<String> errorCallback = null) {
UnityWebRequest get = UnityWebRequest.Get(server);
yield return get.SendWebRequest();
if (get.result != UnityWebRequest.Result.Success) {
Debug.Log(get.error);
if(errorCallback != null)
errorCallback("Cannot make request to " + server +
"\nerror:" + get.error);
yield return false;
}
else {
successCallback(get);
yield return true;
}
}
and this one runs fine.
What should I do to the method to not stops after the first yield return?
EDIT:
I solved the problem!
The reason why this was happening, it was because the gameObject was setting deactivated before the coroutine finishes, so the scripts was stopping
gameObject.SetActive(false);
https://docs.unity3d.com/ScriptReference/GameObject.SetActive.html
The unity documentation says that "Deactivating a GameObject disables each component, including attached renderers, colliders, rigidbodies, and scripts. For example, Unity will no longer call the Update() method of a script attached to a deactivated GameObject. OnEnable or OnDisable are called as the GameObject received SetActive(true) or SetActive(false)." So, as the script is an component attached to the scene object, makes sense that it stops working
Well, yield works by returning results from one iteration,and what comes after will not be executed. In your method, when a call is made to AddObjectById, it will stop at the first yield it finds and return its value, in this case get.SendWebRequest();, not continuing the flow. If you move yield return get.SendWebRequest(); after of if-else, it will never enter, as it will have some return in yield return coming from "if-else".
I found out that if the gameObject is not active gameObject.SetActive(false); the Coroutines stops too. The problem was not with the coroutines but with the gameObject being deactivated

Attempting to load AssetReference that has already been loaded

When I start the main scene and test a new character it shows this error why?
Attempting to load AssetReference that has already been loaded. Handle is exposed through getter OperationHandle
UnityEngine.AddressableAssets.AssetReference:LoadAssetAsync<UnityEngine.GameObject> ()
TrackManager/<SpawnFromAssetReference>d__104:MoveNext () (at Assets/Scripts/Tracks/TrackManager.cs:565)
UnityEngine.MonoBehaviour:StartCoroutine (System.Collections.IEnumerator)
TrackManager:SpawnObstacle (TrackSegment) (at Assets/Scripts/Tracks/TrackManager.cs:556)
TrackManager/<SpawnNewSegment>d__102:MoveNext () (at Assets/Scripts/Tracks/TrackManager.cs:538)
UnityEngine.SetupCoroutine:InvokeMoveNext (System.Collections.IEnumerator,intptr)
my code :
if (m_SafeSegementLeft <= 0)
{
SpawnObstacle(newSegment);
}
else
m_SafeSegementLeft -= 1;
m_Segments.Add(newSegment);
if (newSegmentCreated != null) newSegmentCreated.Invoke(newSegment);
}
public void SpawnObstacle(TrackSegment segment)
{
if (segment.possibleObstacles.Length != 0)
{
for (int i = 0; i < segment.obstaclePositions.Length; ++i)
{
AssetReference assetRef = segment.possibleObstacles[Random.Range(0, segment.possibleObstacles.Length)];
StartCoroutine(SpawnFromAssetReference(assetRef, segment, i));
}
}
StartCoroutine(SpawnCoinAndPowerup(segment));
}
private IEnumerator SpawnFromAssetReference(AssetReference reference, TrackSegment segment, int posIndex)
{
AsyncOperationHandle op = reference.LoadAssetAsync<GameObject>();
yield return op;
GameObject obj = op.Result as GameObject;
if (obj != null)
{
Obstacle obstacle = obj.GetComponent<Obstacle>();
if (obstacle != null)
yield return obstacle.Spawn(segment, segment.obstaclePositions[posIndex]);
}
}
It says i have error in line 565 which is AsyncOperationHandle op = reference.LoadAssetAsync<GameObject>();
What is the error here?
The error message sounds quite self-explanatory: You try to load the same addressable twice.
As said in
AssetReference assetRef = segment.possibleObstacles[Random.Range(0, segment.possibleObstacles.Length)];
you pick a random entry from available addressables. However, nothing here prevents that you get casually the same element twice.
I would rather either keep track of which ones already are loaded
Dictionary<AssetReference, GameObject> loadedAssets = new Dictionary<AssetReference, GameObject>();
and then do
private IEnumerator SpawnFromAssetReference(AssetReference reference, TrackSegment segment, int posIndex)
{
if(!loadedAssets.TryGetValue(reference, out var obj || !obj)
{
loadedAssets.Add(reference, null);
AsyncOperationHandle op = reference.LoadAssetAsync<GameObject>();
yield return op;
obj = op.Result;
loadedAssets[reference] = obj;
}
if(!obj.TryGetComponent<Obstacle>(out var obstacle))
{
Debug.LogError($"No {nameof(Obstacle)} component on loaded object!");
yield break;
}
yield return obstacle.Spawn(segment, segment.obstaclePositions[posIndex]);
}
And then of course whenever you Release one of the loaded assets you also want to
loadedAssets.Remove(reference);
Or depending on your use case and needs load them all and then start your app if you are going to spawn them more often anyway.
Following derHugo approach of storing values I came up with this to always have the addressable result ready to be returned as a gameobject but prevent it to be loaded more than once, addressables also has a 'address.LoadAssetAsync().WaitForCompletion()' method but in my case when loading many things it gets too laggy.
private async Task<T> GetNewInstance<T>(AssetReferenceGameObject address) where T : MonoBehaviour
{
if (!loadedAssetsTask.ContainsKey(address))
{
LoadNewAddress<T>(address);
}
var asset = await loadedAssetsTask[address];
var newGameObject = Instantiate(asset);
var component = newGameObject.GetComponent<T>();
return component;
}
private void LoadNewAddress<T>(AssetReferenceGameObject address) where T : MonoBehaviour
{
var loadedAssetTask = address.LoadAssetAsync().Task;
loadedAssetsTask.Add(address, loadedAssetTask);
}
A little bit late, but after some dig up I found the explaination from Unity_Bill:
AssetReference.LoadAssetAsync() is a helper we've provided that you in
no way need to use when loading an AssetReference.
Addressables.LoadAssetAsync(AssetReference) will work just as well. If
you do the latter, the async operation handle is returned to you and
you are in charge of it. You can call that as many times as you want,
and get as many handles as you want. Each will be ref-counted.
If you choose to use the AssetReference.LoadAssetAsync() helper, the
asset reference itself will hold on to the handle. This enabled the
helper method AssetReference.ReleaseAsset(). Prior to 1.15.1, if you
called load twice, the first handle would simply get stomped. If you
happened to keep up with it, great, but if not, it was lost forever.
So, in short, AssetReference.LoadAssetAsync() is a convenience helper
that really only works in the most simple case. If you are doing
anything beyond the simple, and are keeping up with the handles
yourself, just use Addr.Load... If I were starting addressables over I
likely wouldn't have the helpers at all, requiring the
Addressables.Load..(AssetRef) be used instead.
TLDR: Use Addressables.LoadAssetAsync(AssetReference) instead of AssetReference.LoadAssetAsync
You can read more here: https://forum.unity.com/threads/1-15-1-assetreference-not-allow-loadassetasync-twice.959910/

Can anyone help me with the loadingSceneIndex issue

does anyone know where the error is? I've been looking for various solutions but I didn't get what I wanted
public static void LoadScene(int levelNum)
{
Application.backgroundLoadingPriority = ThreadPriority.High;
sceneToLoad = levelNum;
SceneManager.LoadScene(loadingSceneIndex);
}
Eror : Assets\Script AR\LoadingScreenManager.cs(35,32): error CS0103: The name 'loadingSceneIndex' does not exist in the current context
and one more problem this one
private void StartOperation(int levelNum)
{
Application.backgroundLoadingPriority = loadThreadPriority;
operation = SceneManager.LoadSceneAsync(levelNum, loadSceneMode);
if (loadSceneMode = LoadSceneMode.Single)
operation.allowSceneActivation = false;
}
Eror : Assets\Script AR\LoadingScreenManager.cs(91,13): error CS0029: Cannot implicitly convert type 'UnityEngine.SceneManagement.LoadSceneMode' to 'bool'
The first error happens because the variable loadingSceneIndex doesn't exist. You should plug the scene you want to load into the LoadScene function like this:
SceneManager.LoadScene(levelNum);
That way the LoadScene function knows which scene to load.
The second error happens because in you're if statement expects a bool, but plug in loadSceneMode = LoadSceneMode.Single. That is defining loadSceneMode. Instead, use loadSceneMode == LoadSceneMode.Single instead because that will return a bool.
Note: Have you looked into using something like Intellisense so your editor can detect these errors for you. If you are using Visual Studio, this link might help.

GetComponent isn't working with Unity 5.2

I'm trying to follow along to this tutorial http://wiki.unity3d.com/index.php?title=Server_Side_Highscores
But it hasn't been updated to Unity 5.2 and I can't get the GetComponent to work no matter what I try.
IEnumerator GetScores()
{
GameObject text = new GameObject ("Loading Scores");
text.GetComponent<GUIText>();
WWW hs_get = new WWW(highscoreURL);
yield return hs_get;
if (hs_get.error != null)
{
print("There was an error getting the high score: " + hs_get.error);
}
else
{
GetComponent<GUIText>(hs_get.text); //Line of code not working
// this is a GUIText that will display the scores in game.
}
}
The error is: Assets/HSController.cs(46,25): error CS0308: The non-generic method `UnityEngine.Component.GetComponent(System.Type)' cannot be used with the type arguments
I can't seem to get GetComponent working any help would be greatly appreciated
Have you tried
text.text = hs_get.text;
I'm not entirely sure what your code is supposed to do, but I don't know why you're using GetComponent. If you don't want to reuse the "text" variable, then you could maybe try something like
hsText = GetComponent <GUIText> ();
hsText.text = hs_get.text;
I don't know if I'm addressing the problem but I hope this helps!

What is the fastest way to find out if a string ends with another string?

What is the best rewrite of this method to speed it up?
public static bool EndsWith(string line, string term)
{
bool rb = false;
int lengthOfTerm = term.Length;
string endOfString = StringHelpers.RightString(line, lengthOfTerm);
if (StringHelpers.AreEqual(term, endOfString))
{
return true;
}
else
{
rb = false;
}
if (line == term)
{
rb = true;
}
return rb;
}
Maybe I am missing the point completely, but I would spontaneously go for the String.EndsWith method.
You may want to drop the method rather than rewrite it...
public static bool EndsWith(string line, string term)
{
return line.EndsWith(term);
}
Could you use the .NET builtin in string.Endwith() method?
Can't you just use the standard string.EndsWith() function??
Is there any reason you aren't using the build in String.EndsWith method? I imagine that will be the fastest solution most of the time.
line.EndsWidth(term)

Categories