How have you guys been implementing unity physics systems into your Entitas code? For example lets say you have a gameobject that is linked to an entity and has an event that updates its Transform position based on the entity's position. that works fine because it is transform based, but if you were to move the gameobject through rigid body that updates the transform of the gameobject directly and disregards the entity's position. How does one go about implementing rigid body movement while still keeping the entity in complete control of its gameobject?
The only way I have implemented physics into my entitas system is having the collision emmiter such as this however as I said I dont know how to keep the entity as a master controller of its gameobject while using rigid bodies
public class CollisionEmitter : MonoBehaviour {
public string targetTag;
void OnCollisionEnter(Collision collision) {
if(collision.gameObject.CompareTag(targetTag)) {
var link = gameObject.GetEntityLink();
var targetLink = collision.gameObject.GetEntityLink();
Pools.sharedInstance.input.CreateEntity()
.AddCollision(link.entity, targetLink.entity);
}
}
that is old entitas code btw that I found on how collision can possibly be implemented i must say good idea
Hi,
when gameObjects are controlled by Unity Physics, e.g. Rigidbody, I have a system that syncs the position back to the entity. I only use it when I need to be able to react to the position.
public interface ISyncPosition {
Vector3 position { get; }
}
public class SyncPositionComponent : IComponent {
public ISyncPosition value;
}
public sealed class SyncPositionSystem : IExecuteSystem {
readonly IGroup<GameEntity> _entities;
public SyncPositionSystem(Contexts contexts) {
_entities = contexts.game.GetGroup(GameMatcher.AllOf(GameMatcher.SyncPosition, GameMatcher.Position));
}
public void Execute() {
foreach (var e in _entities) {
e.ReplacePosition(e.syncPosition.value.position);
}
}
}
public class Rigidbody2DView : UnityView, ISyncPosition, IVelocityListener {
public override Vector3 position { get { return base.position; } set { throw new Exception("Rigidbody2DView.position must not be set!"); } }
public override Quaternion rotation { get { return base.rotation; } set { throw new Exception("Rigidbody2DView.rotation must not be set!"); } }
public override Vector3 scale { get { return base.scale; } set { throw new Exception("Rigidbody2DView.scale must not be set!"); } }
Rigidbody2D _rigidbody2D;
public override void Awake() {
base.Awake();
_rigidbody2D = GetComponent<Rigidbody2D>();
}
public override void Link(IEntity entity, IContext context) {
base.Link(entity, context);
base.position = _linkedEntity.position.value;
_linkedEntity.RemovePositionListener();
_linkedEntity.RemoveRotationListener();
_linkedEntity.RemoveScaleListener();
_linkedEntity.AddSyncPosition(this);
_linkedEntity.AddVelocityListener(this);
}
public void OnVelocity(GameEntity entity, Vector3 value) {
_rigidbody2D.velocity = value;
}
}
My next video will be about this topic. If you don't want to miss this, you can subscribe
https://www.youtube.com/DesperateDevs
@sschmid Thanks for the example. 馃憤
@sschmid Could you also post UnityView here?
@sschmid I'm not seeing where this _linkedEntity reference is coming from?
_linkedEntity is defined in one of the base classes (View or UnityView i suppose).
My next video will be about this topic. If you don't want to miss this, you can subscribe
https://www.youtube.com/DesperateDevs
@sschmid I think next video u not only can talk about view service but also audio service since I think audio is part of view.
Heres an example of the views I used for a ping pong game I made with entitas
using Entitas;
using Entitas.Unity;
using System.Linq;
using DG.Tweening;
class BaseGameView : BaseView, IBaseGameView, IGamePositionListener,IGameNameListener
{
public GameEntity gameEntity { get; set; }
public void OnPosition(GameEntity entity, EntitasVec3 value)
{
transform.DOMove(value, .1f);
}
public virtual void Startup(GameEntity entity)
{
gameEntity = entity;
gameEntity.ReplacePosition(new EntitasVec3(transform.position.x, transform.position.y, transform.position.z));
if (tag == "Enemy")
{
gameEntity.isEnemyFlag = true;
}
}
private void Awake()
{
}
protected string Getname()
{
if (name.Contains('('))
{
int index = name.IndexOf("(Clone)");
name = name.Remove(index);
return name;
}
else return name;
}
public virtual void Link(IContext context, IEntity entity)
{
EntityLinkExtension.Link(gameObject, entity, context);
if (gameEntity == null)
{
gameEntity = entity as GameEntity;
}
transform.position = gameEntity.position.value;
gameEntity.AddGamePositionListener(this);
gameEntity.AddGameNameListener(this);
gameEntity.AddBaseGameView(this);
if (gameEntity.hasName)
{
name = gameEntity.name.value;
}
else gameEntity.AddName(Getname());
}
private void OnDestroy()
{
}
public void Unlink()
{
EntityLinkExtension.Unlink(gameObject);
gameEntity.RemoveBaseGameView();
Destroy(gameObject);
}
public void OnName(GameEntity entity, string value)
{
name = value;
}
}
then I had game view that also would be a rigid body
using Entitas;
using UnityEngine;
using Entitas.Unity;
class RigidBodyBaseView : BaseGameView, IRigidBodyView
{
protected Rigidbody rb;
public EntitasVec3 Velocity
{
get
{
return rb.velocity;
}
set
{
throw new UnityException("cannot set Velocity");
}
}
public EntitasVec3 Getvelocity()
{
return rb.velocity;
}
public void InputForce(EntitasVec3 newtons)
{
rb.AddForce(newtons, ForceMode.Acceleration);
}
public void SynchPosition()
{
gameEntity.ReplacePosition(rb.position);
}
private void Awake()
{
rb = gameObject.AddComponent<Rigidbody>();
rb.useGravity = false;
}
public override void Link(IContext context, IEntity entity)
{
base.Link(context, entity);
gameEntity.AddRigidBodyView(this);
}
protected void OnDestroy()
{
if (gameObject.GetComponent<EntityLink>() != null)
EntityLinkExtension.Unlink(gameObject);
gameEntity.RemoveRigidBodyView();
}
}
and then I had a special view for entitys I wanted to be balls
using UnityEngine;
using Entitas;
class BallView : RigidBodyBaseView
{
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.name == "Player Goal")
{
var score = Contexts.sharedInstance.gameState.GetEntitiesWithName("EnemyScore").SingleEntity();
score.ReplaceScore(score.score.value + 1);
gameEntity.isDestory = true;
Destroy(gameObject);
}
if (collision.gameObject.name == "Enemy Goal")
{
var score = Contexts.sharedInstance.gameState.GetEntitiesWithName("PlayerScore").SingleEntity();
score.ReplaceScore(score.score.value + 1);
gameEntity.isDestory = true;
Destroy(gameObject);
}
if(collision.gameObject.name== "PlayerPadle")
{
ServiceManager.DebugMessageService.Print("player paddle hit");
rb.AddForce(new EntitasVec3(100, 0,0));
}
if (collision.gameObject.name == "Enemy Paddle"|| collision.gameObject.name == "Player Two")
{
ServiceManager.DebugMessageService.Print("enemy paddle hit");
rb.AddForce(new EntitasVec3(-100, 0, 0));
}
}
public override void Link(IContext context, IEntity entity)
{
base.Link(context, entity);
gameObject.GetComponent<SphereCollider>().material = Resources.Load<PhysicMaterial>(@"Materials\bouncy");
}
}
Most helpful comment
Hi,
when gameObjects are controlled by Unity Physics, e.g. Rigidbody, I have a system that syncs the position back to the entity. I only use it when I need to be able to react to the position.