Skip to content

Instantly share code, notes, and snippets.

@FNGgames
Last active October 24, 2018 10:27
Show Gist options
  • Save FNGgames/47021f7604d14369426c2aeddbf82dce to your computer and use it in GitHub Desktop.
Save FNGgames/47021f7604d14369426c2aeddbf82dce to your computer and use it in GitHub Desktop.
View layer abstraction for Entitas (with Unity implementation).
using System.Collections.Generic;
using Entitas;
public class AssignGameViewSystem : ReactiveSystem<GameEntity>
{
private readonly Contexts _contexts;
public AssignGameViewSystem(Contexts contexts) : base(contexts.game)
{
_contexts = contexts;
}
protected override ICollector<GameEntity> GetTrigger(IContext<GameEntity> context)
{
return context.CreateCollector(GameMatcher.AssignView);
}
protected override bool Filter(GameEntity entity)
{
return entity.isAssignView && !entity.hasGameView;
}
protected override void Execute(List<GameEntity> entities)
{
foreach (var e in entities)
{
var view = _contexts.meta.contentService.instance.CreateView();
view.Link(e, _contexts.game); // game view component is assigned in here
e.isAssignView = false;
}
}
}
using System.Collections.Generic;
using Entitas;
public class LoadGameAssetSystem : ReactiveSystem<GameEntity>
{
private readonly Contexts _contexts;
public LoadGameAssetSystem(Contexts contexts) : base(contexts.game)
{
_contexts = contexts;
}
protected override ICollector<GameEntity> GetTrigger(IContext<GameEntity> context)
{
return context.CreateCollector(GameMatcher.Asset);
}
protected override bool Filter(GameEntity entity)
{
return entity.hasAsset && !entity.hasGameView;
}
protected override void Execute(List<GameEntity> entities)
{
foreach (var e in entities)
{
var view = _contexts.meta.contentService.instance.LoadAsset(e.asset.name);
if (view == null) continue;
view.Link(e, _contexts.game); // view component assigned in here
}
}
}
using System;
using UnityEngine;
public class UnityContentService : IContentService
{
protected GameObject _viewContainer;
protected GameObject _viewPrototype;
public UnityContentService()
{
// init view container
_viewContainer = new GameObject("Views");
_viewContainer.transform.SetParent(_topViewContainer);
// game prototype is simple game object
_viewPrototype = new GameObject("Game View Prototype");
_viewPrototype.transform.SetParent(_viewContainer.transform);
_viewPrototype.SetActive(false);
}
public IViewController CreateView()
{
// spawn new game view
var gameObject = GameObject.Instantiate(_viewPrototype);
gameObject.transform.SetParent(_viewContainer.transform);
return gameObject.AddComponent<UnityViewController>();
}
public IViewController LoadAsset(string name)
{
// spawn prefab
var prefab = CachedResources.Load<GameObject>("Prefabs/Game/"+ name);
if (prefab == null) return null;
var gameObject = GameObject.Instantiate(prefab);
gameObject.transform.SetParent(_viewContainer.transform)
var view = gameObject.GetComponent<UnityViewController>();
if (view == null) view = prefab.AddComponent<UnityViewController>();
return view;
}
}
using Entitas;
using Entitas.Unity;
using UnityEngine;
public class UnityGameView : MonoBehaviour, IGameView
{
protected GameEntity _entity;
protected SpriteRenderer _spriteRenderer;
protected Rigidbody2D _rigidBody;
protected Collider2D _collider;
// IView
public virtual void SetActive(bool active)
{
gameObject.SetActive(active);
}
public virtual void SetName(string name)
{
gameObject.name = name;
}
public virtual void Link(IEntity entity, IContext context)
{
_entity = (GameEntity) entity;
_entity.ReplaceGameView(this);
gameObject.Link(_entity, context);
_entity.Retain(this);
// if this came from an prefab and not a fresh view, copy values
// from Unity components to entitas components
if (_entity.hasAsset) SyncUnityComponents();
for (var i = 0; i < transform.childCount; i++)
{
var childGo = transform.GetChild(i).gameObject;
var childView = childGo.GetComponent<UnityGameView>();
if (childView == null) childView = childGo.AddComponent<UnityGameView>();
var e = ((GameContext) context).CreateEntity();
childView.Link(e, context);
childView.SyncUnityComponents();
}
}
public virtual void Unlink()
{
gameObject.Unlink();
_entity.Release(this);
_entity = null;
}
public virtual void SetParent(IView parent)
{
var parentView = (UnityGameView) parent;
if (parentView == null) return;
transform.SetParent(parentView.transform);
}
public virtual void RemoveParent()
{
if (_viewContainer != null) transform.SetParent(_viewContainer);
}
public virtual void DestroyView()
{
Destroy(gameObject);
}
// IGraphics
public virtual void SetImage(string name)
{
if (_spriteRenderer == null) _spriteRenderer = gameObject.AddComponent<SpriteRenderer>();
_spriteRenderer.sprite = CachedResources.Load<Sprite>("Sprites/Game/" + name);
}
public virtual void SetImageColor(ColorVector color)
{
if (_spriteRenderer == null) return;
_spriteRenderer.color = new Color(color.r, color.g, color.b, _spriteRenderer.color.a);
}
public virtual void SetImageAlpha(float a)
{
if (_spriteRenderer == null) return;
var color = _spriteRenderer.color;
color.a = a;
_spriteRenderer.color = color;
}
public virtual void SetImageRenderOrder(int order)
{
if (_spriteRenderer == null) return;
_spriteRenderer.sortingOrder = order;
}
public virtual void RemoveImage()
{
if (_spriteRenderer == null) return;
Destroy(_spriteRenderer);
}
// IPhysics
public virtual Vector2D Position
{
get { return _rigidBody != null ? new Vector2D(_rigidBody.position.x, _rigidBody.position.y) : new Vector2D(transform.position.x, transform.position.y); }
set
{
if (_rigidBody != null) _rigidBody.position = new Vector2(value.x, value.y);
else transform.position = new Vector3(value.x, value.y, 0);
}
}
public virtual Vector2D Velocity
{
get { return _rigidBody != null ? new Vector2D(_rigidBody.velocity.x, _rigidBody.velocity.y) : Vector2D.zero; }
set { if (_rigidBody != null) _rigidBody.velocity = new Vector2(value.x, value.y); }
}
public virtual void CreateRigidbody()
{
if (_rigidBody != null) return;
_rigidBody = gameObject.AddComponent<Rigidbody2D>();
_rigidBody.gravityScale = _rigidBody.drag = 0;
_rigidBody.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
_rigidBody.interpolation = RigidbodyInterpolation2D.Extrapolate;
}
public virtual void AddForce(Vector2D force)
{
if (_rigidBody == null) return;
_rigidBody.AddForce(new Vector2(force.x, force.y));
}
public virtual void SetDrag(float drag)
{
if (_rigidBody == null) return;
_rigidBody.drag = drag;
_rigidBody.angularDrag = 10 * drag;
}
public virtual void SetBounciness(float bounciness)
{
if (_rigidBody == null) return;
var mat = new PhysicsMaterial2D { bounciness = bounciness };
_rigidBody.sharedMaterial = mat;
if (_edgeCollider == null && _collider == null) return;
if (_edgeCollider != null) _edgeCollider.sharedMaterial = mat;
if (_collider != null) _collider.sharedMaterial = mat;
}
public virtual void SetMass(float mass)
{
if (_rigidBody == null) return;
_rigidBody.mass = mass;
}
public virtual void SetKinematic(bool isKinematic)
{
if (_rigidBody == null) return;
_rigidBody.isKinematic = isKinematic;
}
public virtual void SetSimulated(bool isSimulated)
{
if (_rigidBody == null) return;
_rigidBody.simulated = isSimulated;
}
public virtual void SetPosition(float x, float y)
{
if (_rigidBody == null) return;
_rigidBody.position = new Vector2(x, y);
}
public virtual void CreateCollider()
{
if (_collider == null) _collider = gameObject.AddComponent<PolygonCollider2D>();
}
public virtual void SetColliderAsTrigger(bool isTrigger)
{
if (_collider != null) _collider.isTrigger = true;
}
public virtual void RemoveRigidbody()
{
if (_rigidBody != null) Destroy(_rigidBody);
}
public virtual void RemoveCollider()
{
if (_collider != null) Destroy(_collider);
}
// sync unity component values to entity component values
protected virtual void SyncUnityComponents()
{
if (!_entity.hasName) _entity.AddName(name);
if (!_entity.hasTag) _entity.AddTag(tag);
_spriteRenderer = GetComponent<SpriteRenderer>();
if (_spriteRenderer != null)
{
_entity.ReplaceImage(_spriteRenderer.sprite.name);
_entity.ReplaceImageColor(_spriteRenderer.color.ToColorVector());
_entity.ReplaceImageAlpha(_spriteRenderer.color.a);
_entity.ReplaceImageRenderOrder(_spriteRenderer.sortingOrder);
}
_rigidBody = GetComponent<Rigidbody2D>();
if (_rigidBody != null)
{
_entity.isRigidbody = true;
_entity.ReplaceMass(_rigidBody.mass);
_entity.ReplaceDrag(_rigidBody.drag);
_entity.ReplaceBounciness(_rigidBody.sharedMaterial.bounciness);
}
_collider = gameObject.GetComponent<Collider2D>();
if (_collider != null) _entity.isCollider = true;
var parent = transform.parent;
if (parent == null) return;
var parentView = transform.parent.gameObject.GetComponent<UnityGameView>();
if (parentView != null) _entity.ReplaceParent(parentView._entity.id.value);
}
}
using Entitas;
public interface IContentService
{
IViewController CreateView();
IViewController LoadAsset(string name);
}
public interface IViewController : IView, IGraphics2D, IPhysics2D
{
}
public interface IView
{
void SetActive(bool active);
void SetName(string name);
void Link(IEntity entity, IContext context);
void Unlink();
void SetParent(IView parent);
void RemoveParent();
void DestroyView();
}
public interface IGraphics2D
{
void SetImage(string name);
void SetImageColor(ColorVector color);
void SetImageAlpha(float a);
void SetImageRenderOrder(int order);
void RemoveImage();
}
public interface IPhysics2D
{
Vector2D Position { get; set; }
Vector2D Velocity { get; set; }
void AddForce(Vector2D force);
void SetDrag(float drag);
void SetBounciness(float bounciness);
void SetMass(float mass);
void SetKinematic(bool isKinematic);
void SetSimulated(bool isSimulated);
void CreateRigidbody();
void CreateCollider();
void SetColliderAsTrigger(bool isTrigger);
void RemoveRigidbody();
void RemoveCollider();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment