I have started to encounter an editor crash around this section, although I suspect it’s been around much longer. It seems whenever I am using an ability and hover the mouse over the edge of the map, it freezes up and I need to task manager the editor out. Anybody know what might be causing this? I care less if it’s unlikely to happen in the actual game but I’d still like to fix it either way. My only guess is that it has to do with the raycast going to effectively infinity, but it should have a limit of 1000 anyways as written in the course’s code.
I’m assuming you mean something like the DelayedClickTargeting.cs that’s the root of the problem?
Paste in your DelayedClick.cs and we’ll take a look.
using System;
using System.Collections;
using System.Collections.Generic;
using RPG.Control;
using UnityEngine;
namespace RPG.Abilities
{
[CreateAssetMenu(fileName = "Delayed Click Targeting", menuName = "Abilities/Targeting/DelayedClick", order = 0)]
public class DelayedClickTargeting : TargetingStrategy
{
[SerializeField] Texture2D cursorTexture;
[SerializeField] Vector2 cursorHotspot;
[SerializeField] LayerMask layerMask;
[SerializeField] float areaEffectRadius;
[SerializeField] Transform targetingPrefab;
[SerializeField] float yOffset = .5f;
Vector3 tempPosition;
Transform targetingPrefabInstance = null;
public override void StartTargeting(AbilityData data, Action finished)
{
PlayerController playerController = data.GetUser().GetComponent<PlayerController>();
playerController.StartCoroutine(Targeting(data, playerController, finished));
}
private IEnumerator Targeting(AbilityData data, PlayerController playerController, Action finished)
{
playerController.enabled = false;
if(targetingPrefabInstance == null)
{
targetingPrefabInstance = Instantiate(targetingPrefab);
}
else
{
targetingPrefabInstance.gameObject.SetActive(true);
}
targetingPrefabInstance.localScale = new Vector3(areaEffectRadius*2, areaEffectRadius*2, 1);
while (true)
{
Cursor.SetCursor(cursorTexture, cursorHotspot, CursorMode.Auto);
RaycastHit raycastHit;
if (Physics.Raycast(PlayerController.GetMouseRay(), out raycastHit, 1000, layerMask))
{
tempPosition.x = raycastHit.point.x;
tempPosition.z = raycastHit.point.z;
tempPosition.y = raycastHit.point.y+yOffset;
targetingPrefabInstance.position = tempPosition;
if(Input.GetMouseButtonDown(0))
{
while(Input.GetMouseButton(0))
{
yield return null;//Prevents using ability from accidentally left clicking for other kinds of commands, like walking
}
playerController.enabled = true;
targetingPrefabInstance.gameObject.SetActive(false);
data.SetTargetedPoint(raycastHit.point);
data.SetTargets(GetGameObjectsInRadius(raycastHit.point));
finished();
yield break;
}
yield return null;
}
}
}
private IEnumerable<GameObject> GetGameObjectsInRadius(Vector3 point)
{
RaycastHit[] hits = Physics.SphereCastAll(point, areaEffectRadius, Vector3.up, 0);
foreach (var hit in hits)
{
yield return hit.collider.gameObject;
}
}
}
}
I wasn’t able to duplicate the error in a course project using your script (though there are some issues with the display of the targeting prefab…
For a start, change the scale code from
targetingPrefabInstance.localScale = new Vector3(areaEffectRadius*2, areaEffectRadius*2, 1);
to
targetingPrefabInstance.localScale = new Vector3(areaAffectRadius*2, 1, areaAffectRadius*2);
In other respects, going outside of the game window (even moving the cursor to screen 2) appeared to function normally.
I suspect that this may be a bug in the current version of Unity.
One thing you could do is to add a filter:
using System;
using System.Collections;
using System.Collections.Generic;
using RPG.Control;
using UnityEngine;
namespace RPG.Abilities
{
[CreateAssetMenu(fileName = "Delayed Click Targeting", menuName = "Abilities/Targeting/DelayedClick", order = 0)]
public class DelayedClickTargeting : TargetingStrategy
{
[SerializeField] Texture2D cursorTexture;
[SerializeField] Vector2 cursorHotspot;
[SerializeField] LayerMask layerMask;
[SerializeField] float areaEffectRadius;
[SerializeField] Transform targetingPrefab;
[SerializeField] float yOffset = .5f;
Vector3 tempPosition;
Transform targetingPrefabInstance = null;
public override void StartTargeting(AbilityData data, Action finished)
{
PlayerController playerController = data.GetUser().GetComponent<PlayerController>();
playerController.StartCoroutine(Targeting(data, playerController, finished));
}
private IEnumerator Targeting(AbilityData data, PlayerController playerController, Action finished)
{
playerController.enabled = false;
if (targetingPrefabInstance == null)
{
targetingPrefabInstance = Instantiate(targetingPrefab);
}
else
{
targetingPrefabInstance.gameObject.SetActive(true);
}
targetingPrefabInstance.localScale = new Vector3(areaEffectRadius * 2, 1, areaEffectRadius * 2);
Rect screenBounds = new Rect(0, 0, Screen.width, Screen.height);
while (true)
{
if (!screenBounds.Contains(Input.mousePosition))
{
targetingPrefabInstance.gameObject.SetActive(false);
yield return null;
}
else
{
targetingPrefabInstance.gameObject.SetActive(true);
Cursor.SetCursor(cursorTexture, cursorHotspot, CursorMode.Auto);
RaycastHit raycastHit;
if (Physics.Raycast(PlayerController.GetMouseRay(), out raycastHit, 1000, layerMask))
{
tempPosition.x = raycastHit.point.x;
tempPosition.z = raycastHit.point.z;
tempPosition.y = raycastHit.point.y + yOffset;
targetingPrefabInstance.position = tempPosition;
if (Input.GetMouseButtonDown(0))
{
while (Input.GetMouseButton(0))
{
yield return
null; //Prevents using ability from accidentally left clicking for other kinds of commands, like walking
}
playerController.enabled = true;
targetingPrefabInstance.gameObject.SetActive(false);
data.SetTargetedPoint(raycastHit.point);
data.SetTargets(GetGameObjectsInRadius(raycastHit.point));
finished();
yield break;
}
}
yield return null;
}
}
}
private IEnumerable<GameObject> GetGameObjectsInRadius(Vector3 point)
{
RaycastHit[] hits = Physics.SphereCastAll(point, areaEffectRadius, Vector3.up, 0);
foreach (var hit in hits)
{
yield return hit.collider.gameObject;
}
}
}
}
The idea here is that if the cursor is out of the game window, then we simply turn off the selection object and yield return null, thus making no attempts to Raycast outside of the game window.
I’m not positive that this will fix the issue, because if this were the issue we’d have ran into it in the regular game loop.
Just to confirm, you tested aiming an ability while placing the mouse off the map’s edge right, not the screen’s edge?
OH. No, I didn’t. I put the script into the Course project, and we sort of go out of our way to put dummy terrain on the borders, so you never actually see an area that doesn’t have terrain…
That being said, I’ve used this script within a project that generates procedural levels where empty spaces are nothing, and have not experienced this crash. (In fact, I just went in and tested it now).
It could well be a bug with Unity then, I don’t really have an easy way to check for that. I guess I will have to see if the game has the bug when I actually finish and compile it, unless you have a quicker solution.
Update: I plugged your version of the script (with the corrected scale of X and Z instead of X and Y) into SpellBorne Hunter (my WEP), and when the cursor went over areas with no map, the targetng circle simply froze at the edge of the existing map and the cursor kept on. If I clicked, nothing happened (because the if statement determined there was no hit).
This may very well be a version bug creeping in. Which version of Unity are you using?
21.3.18f1
The scale thing is because my circle prefab seems to be oriented funny, by the way. Realistically, I should just fix the prefab but that’s why the code is currently as it is; otherwise the prefab doesn’t resize right.
That’s strange, because it’s making the circle taller, not deeper. May be a mistake in the setup of your summoning circle.
Yeah, that’s what it is. I had somewhat known that was the issue (with the rotation, not the freezing bug) but got lazy. I fixed it now.
I’ve moved Spellbourne Hunter to 2021.3.18f1, I’ll see if the error happens.
As in the 2.x version it was running in, I’m not experiencing the freeze.
This is becoming quite the mystery.
Zip up your project and upload it to http://gdev.tv/projectupload and I’ll see if I can duplicate this.
Submitting now. Note that I’ve been using “Fire Burst” specifically. “Fire Spray” is my (currently messed up) attempt to go through the projectile effect sections of this course. I think both can produce the crash though.
It did not go through… Usually if the file is too large, it says so in the upload form.
Might just be a googly thing. Maybe wait a few hours and try again.
Sorry for the trouble, but this is still acting funky. Maybe I need a completely new ticket? I think you need to send one on your end, unless I misunderstand the system.
No ticket is required, just the URL I think it does require that you’re logged into a Google account.