GitHub - tongtunggiang/unity-entt (original) (raw)
Introduction
Just a little tech demo of a native simulation layer written in C++ using EnTT and Unity as a rendering engine.
Cloning the project
Remember to clone the repo with submodules
git clone --recurse-submodules -j8 <repo-link>
Setup
For VS2019, run NativeScript/Targets/Generators/VS2019.bat
.
Alternatively, you can run CMake to generate the VS solution suitable to the version you have using command line:
cmake -S ../.. -B ../VS2019 -G "Visual Studio 16 2019" -DCMAKE_CONFIGURATION_TYPES="Debug;Release;" -DEDITOR=ON
Visual Studio solution is now generated in NativeScript/Targets/VS2019/NativeScript.sln
.
Getting Started
Native gameplay
All simulation code files are currently be stored inside NativeScript/Source/Simulation
, with the components are structs prefixed with C
and systems are free functions prefixed with S
. Component structs only support primitive types for now to make sure that they are generated properly on the C# side.
Example:
struct CPosition { Vector3 value; }
void SUpdateMoveForward(Registry& registry, float deltaTime) { PROFILER_FUNCTION();
registry.view<CPosition, COrientation, CMoveSpeed>().each(
[deltaTime](auto entity, CPosition& position, const COrientation& orientation, const CMoveSpeed& moveSpeed)
{
position.value += deltaTime * moveSpeed.value * orientation.value;
}
);
PROFILER_END();
}
Code generator
Structs are parsed and generated to C# counterparts in the precompile stage of the native layer, writing to ECSBindings.cpp/cs as it succeeds.
public struct CPosition { public Vector3 value; }
class ECSBindings { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate CPosition GetPositionType(UInt32 entity); public static GetPositionType GetPosition;
//....
public static void Load()
{
GetPosition = Bindings.GetDelegate<GetPositionType>(libraryHandle, "GetPosition");
}
}
Unity side:
With the component struct all properly compiled, generated and ready for interopping, the final piece of the puzzle is to render it with Unity.
[RequireComponent(typeof(Native.BaseNativeEntityView))] public class EntityPositionView : MonoBehaviour { [SerializeField] bool m_UpdateOnce; [SerializeField] bool m_ViewPosition; [SerializeField] bool m_ViewOrientation;
Native.BaseNativeEntityView m_View;
void Start()
{
m_View = GetComponent<Native.BaseNativeEntityView>();
}
void Update()
{
if (m_ViewPosition)
{
Vector3 pos = ECSBindings.GetPosition(m_View.EntityRef).value;
transform.position = new Vector3(pos.x, pos.y, pos.z);
}
if (m_ViewOrientation)
{
Vector3 orientation = ECSBindings.GetOrientation(m_View.EntityRef).value;
transform.forward = new Vector3(orientation.x, orientation.y, orientation.z);
}
if (m_UpdateOnce)
{
enabled = false;
}
}
}
Useful resources
- The awesome ECS library EnTT.
- Jackson Dunstan's C++ Scripting series.