Created
July 16, 2018 02:39
-
-
Save randomPoison/f3c08206c5055e3c746d8b14b20721d6 to your computer and use it in GitHub Desktop.
Comparison of writing a system with Unity's new ECS vs writing one in Amethyst.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use ::{FrameId, WriteConnection}; | |
use amethyst::ecs::prelude::{Read, System}; | |
use amethyst::input::InputHandler; | |
use core::{ | |
ClientMessage, | |
ClientMessageBody, | |
InputFrame, | |
math::*, | |
}; | |
#[derive(Debug)] | |
pub struct PlayerInputSystem; | |
#[derive(SystemData)] | |
pub struct Data<'s> { | |
input: Read<'s, InputHandler<String, String>>, | |
connection: WriteConnection<'s>, | |
frame_id: Read<'s, FrameId>, | |
} | |
impl<'s> System<'s> for PlayerInputSystem { | |
type SystemData = Data<'s>; | |
fn run(&mut self, mut data: Self::SystemData) { | |
let forward_backward = data.input.axis_value("forward_backward").expect("forward_backward axis not found"); | |
let left_right = data.input.axis_value("left_right").expect("forward_backward axis not found"); | |
let input = InputFrame { | |
// TODO: Is it a good idea to downcast from `f64` here? Would it make more sense to keep the input as `f32`? | |
movement_dir: Vector2::new(left_right as f32, forward_backward as f32), | |
yaw_delta: 0.0, | |
pitch_delta: 0.0, | |
revolver_actions: Vec::new(), | |
}; | |
// TODO: Send the real input state to the server. | |
data.connection.send(ClientMessage { | |
frame: data.frame_id.0, | |
body: ClientMessageBody::Input(input), | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Unity.Entities; | |
using Unity.Mathematics; | |
using UnityEngine; | |
using Unity.Transforms2D; | |
namespace TwoStickPureExample | |
{ | |
public class PlayerMoveSystem : ComponentSystem | |
{ | |
public struct Data | |
{ | |
public readonly int Length; | |
public ComponentDataArray<Position2D> Position; | |
public ComponentDataArray<Heading2D> Heading; | |
public ComponentDataArray<PlayerInput> Input; | |
} | |
[Inject] private Data m_Data; | |
protected override void OnUpdate() | |
{ | |
var settings = TwoStickBootstrap.Settings; | |
float dt = Time.deltaTime; | |
for (int index = 0; index < m_Data.Length; ++index) | |
{ | |
var position = m_Data.Position[index].Value; | |
var heading = m_Data.Heading[index].Value; | |
var playerInput = m_Data.Input[index]; | |
position += dt * playerInput.Move * settings.playerMoveSpeed; | |
if (playerInput.Fire) | |
{ | |
heading = math.normalize(playerInput.Shoot); | |
playerInput.FireCooldown = settings.playerFireCoolDown; | |
PostUpdateCommands.CreateEntity(TwoStickBootstrap.ShotSpawnArchetype); | |
PostUpdateCommands.SetComponent(new ShotSpawnData | |
{ | |
Shot = new Shot | |
{ | |
TimeToLive = settings.bulletTimeToLive, | |
Energy = settings.playerShotEnergy, | |
}, | |
Position = new Position2D{ Value = position }, | |
Heading = new Heading2D{ Value = heading }, | |
Faction = Factions.kPlayer, | |
}); | |
} | |
m_Data.Position[index] = new Position2D {Value = position}; | |
m_Data.Heading[index] = new Heading2D {Value = heading}; | |
m_Data.Input[index] = playerInput; | |
} | |
} | |
} | |
} |
Another similarity that I've noted is that both Unity and Specs provide a way to parallelize iteration of components within a system. It looks like Unity's version is a bit more thought out at this point (it breaks components into chunks of several thousand and those chunks can be processed in parallel, whereas it seems like specs tries to parallelize each component), but the core structure of "systems are run in parallel, and then iteration over components within a system can also proceed in parallel" is largely the same.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This gist compares writing a system in Unity (with the preview version of Unity's ECS) to writing one in Amethyst (using specs). The key similarities to note:
System
trait in Amethyst, inheriting fromComponentSystem
in Unity).Data
struct in both examples).