- A* version: [5.24]
- Unity version: [2022.3.50f1]
Recently upgraded my project to A* 5.x and my live recompile solution broke with the new changes.
Luckily I was able to get it working again with some hacks.
Attach this script to the AStar pathfinder to rescan the navmesh and re-assign the static AstarPath variable on live recompile
using UnityEngine;
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif
/// IMPORTANT!!!!
/// PLACE THIS SCRIPT ABOVE ASTAR IN THE SCRIPT EXECUTION ORDER IN PROJECT SETTINGS IN UNITY (EDIT MENU)
[Serializable]
public class AStarLiveRecompile : MonoBehaviour
{
#if UNITY_EDITOR
void OnEnable()
{
if (EditorApplication.isUpdating) // catch the live reload
{
AstarPath.active = GetComponent<AstarPath>();
if(EditorApplication.isUpdating)
Invoke(nameof(Scan),1f);
}
}
public void Scan()
{
AstarPath.active.Scan();
}
#endif
}
Then make these modifications to A*Project AIBase.cs line 382 to avoid an exception error
// When using rigidbodies all movement is done inside FixedUpdate instead of Update
bool fixedUpdate = rigid != null || rigid2D != null;
if(!BatchedEvents.Has(this))
BatchedEvents.Add(this, fixedUpdate ? BatchedEvents.Event.FixedUpdate : BatchedEvents.Event.Update, OnUpdate);
}
And remove this from AStarPath.cs line 1256 to prevent AStarPath from sabotaging the domain reload
// Note that the first time the component loads, then Awake will run first
// and will already have set the #active field.
// In the editor, OnDisable -> OnEnable will be called when an undo or redo event happens (both in and outside of play mode).
/*if (active != null) {
if (active != this && Application.isPlaying) {
if (this.enabled) {
Debug.LogWarning("Another A* component is already in the scene. More than one A* component cannot be active at the same time. Disabling this one.", this);
}
enabled = false;
}
return;
}*/
// Very important to set this. Ensures the singleton pattern holds
active = this;
AStar will now function with a live recompile and re-scan the graph, it’s a bit hacky but it works. Maybe in the future we could see a proper solution but for now this works.
1 Like
Wow that’s really neat, appreciate the contribution for this. I’ll also tag @aron_granberg to see if he has any more info on this.
I’m confused as to why you need this. The live reload thing will first disable the AIPath, and then enable it again once the live reload is done, right?
The AIPath should unregister from the BatchedEvents during OnDisable.
Because I want to write and modify my code while the game is running to stop wasting time stopping and running the project again. Unity supports this in a limited sense as long as you follow some simple rules. It saves me a great deal of time and frustration.
I go into details here
But if you want please try these changes and try live recompiling on your samples to see for yourself. I am using recast graph with RichAi with RVO and some navmeshcuts so I have no idea if it works in the other AI pathfinders like the follower entity.
I didn’t spend a lot of time figuring out why it was working, I just corrected the errors during the domain reload and rescanned the graph and went about my day. If you want I can share more details over a zoom chat or something.
Sorry. I didn’t mean why do you need live reload. I mean why do you need to make that particular change to the AIBase.cs script.
to avoid adding a duplicate
static void Add<T>(T obj, Event eventTypes, System.Action<T[], int, TransformAccessArray, Event> action1, System.Action<T[], int> action2, int archetypeVariant = 0) where T : Component, IEntityIndex {
if (obj.EntityIndex != 0) {
throw new System.ArgumentException("This object is already registered. Call Remove before adding the object again.");
}
There’s most certainly a better way to do what I did, I just did what was most convinient at the time (forcing live recompiles and fixing errors till they went away) and to get live recompile working so I could continue on other tasks. It would be great if A*Project was more robust to these situations, but I’m happy with it working as it is for now. I also added ALine to my project so thanks for that as well.
1 Like
I’ve simplified the solution, no need to put the AStarLiveRecompile sciprt before execution order of AStar, this was the case from my previous implementation, so remove it. The script should execute after the exectuion order of AStar to reset the global AstarPath.active and rescan the graph
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class AStarLiveRecompile : MonoBehaviour
{
#if UNITY_EDITOR
void OnEnable()
{
if (EditorApplication.isUpdating)
{
AstarPath.active = GetComponent<AstarPath>();
AstarPath.active.Scan();
}
}
#endif
}