- Home /
Using SystemBase (ECS/DOTS) but code will not execute at all!
Hello there,
I apologize ahead of time if the solution to my problem is so simple I should have seen it earlier - for some reason though, I cannot (for the life of me) seem to get my SystemBase
scripts to execute/register ANY code/input!
For example:
I follow this video to start using prefabs: https://www.youtube.com/watch?v=m9YAxRhCZ8M&t=459s&ab_channel=TurboMakesGames
But got stuck at Input.GetKeyDown(KeyCode.A)
- as mine did not want to register/execute! I tried changing a few things to just get my code to debug a log at least, but still nothing~
I'm at a loss - if anyone is able to assist me it would be greatly appreciated!
Sincerely,
Bakos13
PS. I googled my issue but it seems no one else is having it! aha.. so.. Where did I go wrong! I know I installed all the required ECS packages as instructed in the video.
com.unity.rendering.hybrid (which installs all pre-requisites for entities, mathematics, etc)
com.unity.physics
com.unity.netcode
My SystemBase script for spawning entities via prefab:
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
using Random = Unity.Mathematics.Random;
[UpdateBefore(typeof(TransformSystemGroup))]
public partial class gameController : SystemBase
{
private Entity _playablePrefab;
private Entity _capsuleSpawner;
private Random _random;
private float3 _minPos = float3.zero;
private float3 _maxPos = new float3(50, 0, 50);
private BeginSimulationEntityCommandBufferSystem _ecbSystem;
protected override void OnStartRunning()
{
Application.targetFrameRate = 30;
_playablePrefab = GetSingleton<Playable>().Value;
_random.InitState(4554);
_ecbSystem = World.GetOrCreateSystem<BeginSimulationEntityCommandBufferSystem>();
_capsuleSpawner = GetSingletonEntity<LastSpawnedPlayable>();
Debug.Log("1");
}
protected override void OnUpdate()
{
if (Input.GetKey(KeyCode.A))
{
Debug.Log("A");
var newPlayable = EntityManager.Instantiate(_playablePrefab);
SetSingleton(new LastSpawnedPlayable { Value = newPlayable });
var randPos = _random.NextFloat3(_minPos, _maxPos);
var newPos = new Translation { Value = randPos };
EntityManager.SetComponentData(newPlayable, newPos);
Debug.Break();
}
if (Input.GetKeyDown(KeyCode.S))
{
var ecb = _ecbSystem.CreateCommandBuffer();
var newCapsule = ecb.Instantiate(_playablePrefab);
var randPos = _random.NextFloat3(_minPos, _maxPos);
var newPos = new Translation { Value = randPos };
ecb.SetComponent(newCapsule, newPos);
}
var lastSpawned = GetSingleton<LastSpawnedPlayable>().Value;
if (lastSpawned != Entity.Null)
{
var lastPos = GetComponent<Translation>(lastSpawned);
var upPos = new float3(25, 25, 25);
Debug.DrawLine(lastPos.Value, upPos, Color.red);
}
}
}
Answer by andrew-lukasik · May 22 at 08:11 PM
What you just discovered is that OnUpdate
is not always called. Seems surprising but this is a good thing; a feature, not a bug.
Let me explain:
Every system does something to very specific set of components ( a.k.a. query
), right?
So... since this set of components is known ahead of time - the ecs engine will only call OnUpdate
for systems for which entities with a matching set of components exist (!)
The problem in your case is that you didn't realize that query was automagically deduced from the code you wrote. Long story short: ecs figured out that your system does something either to Playable
or lastSpawnedPlayable
components, so there is no point in updating this system without them present in the World
first (system is asleep until one of them appears).
Always look into Systems
window. it displays this information here:
TL;DR: adding
[AlwaysUpdateSystem]
attribute to your system will ignore query requirements for system updates.
Thank you so much Andrew! You just - quite literally - blew my mind with that response!
This ECS system is VERY intimidating at first!