ACTORS is a complete game framework with multiscene editing, game object pooling and ECS ( entity-component-system ) data-driven approach for game logic explicitly built for Unity3d. It is used to ease the pain of decoupling data from behaviors without tons of boilerplate code and without unnecessary overhead.
Features
ECS events ( can be extended with Unirx )
Very lightweight ECS syntax
Actors ( visual entity composer in the Unity Inspector window )
Built-in support for pooling
Built-in support for Unity multiscene editing
Built-in support for plugins with a pluggable wrapper that you can share with others/through projects
Built-in support for updates through ITick, ITickFixed, ITickLate - ( faster than Unity Update methods )
Signals ( in-memory publish/subscribe system and effectively replace Unity3d SendMessage )
Tags ( add simple tags to entities to define states )
Editor extensions ( foldout group in the inspector and tags editing )
Numerous monobehavior components to help interact with the framework
Templates for creating scriptable objects
Game console plugin for commands and cheats
Framework can be extended with ODIN inspector
Requirements
Unity 2018 and higher
How to Install
From packages
Create a new Unity Project
Open the manifest.json file in the Packages folder inside of the Project
Or add ID to manipulate with group of timers that belong to one object.
Timer.Add(0.1f, actor.HandleDestroyGO).AddID(actor);
var timers = Timer.FindAllTimers(actor);
if (timers != null)
for (var i = 0; i < timers.Count; i++)
{
timers[i].timeScale = 0.5f;
}
Added documentation for ECS approach.
Simple ECS pattern for working with actors. My approach can be used only with actor classes at the current moment and is far less powerful than clean ECS approaches and it’s used more for structuring than gaining performance boost.
public class ProcessingCameraFollow : ProcessingBase, ITick, IMustBeWipedOut{
[GroupBy(Tag.GroupPlayer)]
[GroupExclude(Tag.StateDead)]
private Group groupPlayers;
public ProcessingCameraFollow()
{
groupPlayers.OnGroupChanged += OnGroupPlayersChanged;
}
void OnGroupPlayersChanged()
{
for(var i=0;i<groupPlayers.length;i++){
Debug.Log("Actor: " + groupPlayers.actors[i]);
}
}
public void Tick()
{
for(var i=0;i<groupPlayers.length;i++){
DoSomething(groupPlayers.actors[i]);
}
}
void DoSomething(Actor a){
}
}
Added descriptions for tags
Tags are the glue for your game: You can identify your actors with tags or use them as arguments for your signals to check game logic. Tags are simple cont INT variables.
// Add stun marker from the mighty hammer of doom.
tags.Add(Tag.Stunned);
// Add stun marker from falling off the tree.
tags.Add(Tag.Stunned);
// remove effect caused by the mighty hammer of doom.
tags.Remove(Tag.Stunned);
// we are still stunned because we added two stun effects and removed only one
bool condition_stunned = tags.Contain(Tag.Stunned);
Tags can be used in the Inspector window.
public static partial class Tag
{
[TagField(categoryName = "Weapons")] public const int WeaponGun = 9000;
[TagField(categoryName = "Weapons/BigGuns")] public const int WeaponLaser = 9001;
}
A small but important update. Now after saving a new scene, it will be automatically added to project build and generate unique data_yourscenename asset that you need to put inside of your starters. Also, I’ve added special enum helper to ease scenes navigation via code.
Comparing to unity for example I have ultra fast get component calls.
Profile Framework get method took 0.057234000 seconds to complete over 20 iterations, averaging 0.002861700 seconds per call
Profile Unity get component method took 0.113563100 seconds to complete over 20 iterations, averaging 0.005678155 seconds per call
if (Input.GetKeyDown(KeyCode.Space))
{
Profile.StartProfile("Framework get method");
for (int i = 0; i < 100000; i++)
{
Get<Rigidbody2D>();
}
Profile.EndProfile("Framework get method");
Profile.StartProfile("Unity get component method");
for (int i = 0; i < 100000; i++)
{
gameObject.GetComponent<Rigidbody2D>();
}
Profile.EndProfile("Unity get component method");
Profile.PrintResults();
}
All my game runs from single update method. I run some tests making about 10 000 unity objects with updates vs actors with ticks and it was about ~30% performance boost. ( it was about year ago so maybe unity devs made Update method better than it was )
Hi everyone It’s been a while since the last news about the framework, but it continues to evolve. I love ECS paradigm and happy to share my vision on the programming workflow.
Component holds variables.
using UnityEngine;
namespace Homebrew
{
[System.Serializable]
public class ComponentInputExample : IComponent
{
public KeyCode Up;
public KeyCode Right;
public KeyCode Down;
public KeyCode Left;
}
// I generate methods below from a template in IDE
public static class ExtensionComponentInputExample
{
public static ComponentInputExample ComponentInputExample(this int entity) { return Storage<ComponentInputExample>.Instance.components[entity]; }
public static bool HasComponentInputExample(this int entity) { return Storage<ComponentInputExample>.Instance.HasComponent(entity); }
}
}
An actor is a monobehavior component that “link” unity with an abstract entity.
public class ActorExample : Actor
{
[FoldoutGroup("Setup")] public ComponentInputExample componentInputExample;
protected override void Setup()
{
Add(componentInputExample);
}
}
Processings are either systems or some “global” game controllers. Usually, you would add them to the toolbox from starter scripts.
using UnityEngine;
namespace Homebrew
{
public class ProcessingExampleInput : ProcessingBase, ITick
{
// A group is a container of all entities that have certain components.
public Group<ComponentInputExample, ComponentObject> groupInput;
public void Tick()
{
// loop through entities in group
foreach(var entity in groupInput)
{
// get component from group.
var cInputExample = entity.ComponentInputExample();
var cObject = entity.ComponentObject();
if (Input.GetKeyDown(cInputExample.Up))
Debug.Log(cObject.obj + " UP!" );
if (Input.GetKeyDown(cInputExample.Down))
Debug.Log(cObject.obj + " DOWN!" );
if (Input.GetKeyDown(cInputExample.Right))
Debug.Log(cObject.obj + " RIGHT!" );
if (Input.GetKeyDown(cInputExample.Left))
Debug.Log(cObject.obj + " LEFT!" );
}
}
}
}
Starters are classes that initialize scene and can be used to add all processing you would need on the level. Developers control what scenes to load from starter scripts. Using add method in starter class is equal to Toolbox.Add();
public class StarterLevel1: Starter
{
protected override void Setup()
{
Add<ProcessingExampleInput>();
}
}
Уважаемый, здравствуйте! Я чайник в Unity, у меня версия 2019.1.2, пытаюсь добавить ваш фреймворк, вкладку Tools в упор не нашел. Открывал ваш демо проект CryoshockMini-master, в манифесте уже прописан адрес GIT репозитория, Unity мне сообщает о неверном запросе.
An error occurred while resolving packages:
Project has invalid dependencies:
com.pixeye.ecs: Error when executing git command. fatal: unable to access ‘GitHub - PixeyeHQ/actors.unity: 🚀Actors is a framework empowering developers to make better games faster on Unity.’: Failed to connect to github.com port 443: Bad access
подскажите в чем проблема?