Skip to content

Instantly share code, notes, and snippets.

@VaclavElias
Last active January 15, 2022 20:48
Show Gist options
  • Save VaclavElias/8e84331f73d38386021e5f2d34216489 to your computer and use it in GitHub Desktop.
Save VaclavElias/8e84331f73d38386021e5f2d34216489 to your computer and use it in GitHub Desktop.
Stride Code Only Preview 4

Review 4

Feedback from @Eideren and @manio143.

Thanks for your feedback. I think your feedback can be merged together. Note again, that the naming convention can be changed to anything appropriate at the later stage.

If I forgot to address anything you mentioned previously, please feel free to mention that again. Once our thoughts are more stable. I will ping all others who expressed interest in the code-only approach.

https://github.com/VaclavElias/Stride3DTutorials/tree/main/Other/Minimal https://github.com/VaclavElias/stride/tree/code-only

Regarding the method signature which I left below as an example I have got these findings:

  • I wouldn't add there IServiceRegistry, because we can easily reach it with game.Services
  • GameTime is probably ok, because it is deeper, unless we would like to take it further and we would use TimeSpan which would return Elapsed
  • With Scene, there are a few issues
    • The Scene is created through game.SetupBase3DScene(), so it doesn't make sense to pass it through signature because it doesn't exist yet.
    • It could be passed if
      • The Scene was created in the RootScript
      • Or there would be another extension game.SetupBase() called before game.Run(start: Start, update: Update) in the user project
      • Or by updating SceneSystem.cs LoadContent() and adding
      if (sceneTask == null)
      {
          SceneInstance ??= new SceneInstance(Services) { RootScene = new Scene() };
      }
      • Or we don't have to have this convenience yet, maybe to start with, I wouldn't add it and based on the further feedback from others we could elaborate on this further. Unless you can see from your experience that it is worth it to implement it.

Engine Game.cs

2 lines of code added instead of 14.

public Action OnInitialize;  //new line, not sure if you want to have it this way, using Action 

protected override void Initialize() 
{ 
  ... 
  OnInitialize?.Invoke(); //new line, end of the method. 
}

RootScript.cs

Bassed on your feedback, it might be simplified just to

public class RootScript : SyncScript
{
    private readonly Action? startAction;
    private readonly Action<GameTime>? updateAction;
    
    public RootScript(Action? start = null, Action<GameTime>? update = null)
    {
        startAction = start;
        updateAction = update;
    }

    public override void Start()
    {
        startAction?.Invoke();
    }

    public override void Update()
    {
        updateAction?.Invoke(Game.UpdateTime);
    }    
}    

If we want other bits and we figure out how to get Scene

public class RootScript : SyncScript
{
    private readonly Action<Scene, IServiceRegistry>? startAction;
    private readonly Action<Scene, IServiceRegistry, GameTime>? updateAction;

    public RootScript(Action<Scene, IServiceRegistry>? start = null, Action<Scene, IServiceRegistry, GameTime>? update = null)
    {
        startAction = start;
        updateAction = update;
    }

    public override void Start()
    {
        //create empty scene here so it can be passed
        //SceneSystem.SceneInstance ??= new SceneInstance(Services) { RootScene = new Scene() };

        startAction?.Invoke(SceneSystem.SceneInstance?.RootScene, Services);
    }

    public override void Update()
    {
        updateAction?.Invoke(SceneSystem.SceneInstance?.RootScene, Services, Game.UpdateTime);
    }
}

GameExtensions.cs

https://github.com/VaclavElias/Stride3DTutorials/blob/main/Other/Minimal/Stride.GameDefaults/GameExtensions.cs

Code Only Examples

Example 1 .NET 6, C# 10

Nice and clean, encouraging using Components approach and using Script Components.

using var game = new Game();

game.Run(start: Start, update: null);

void Start(Scene rootScene, IServiceRegistry services)
{
    // adds scene, graphics comositor, camera, camera script, skybox, ground ..like through UI
    game.SetupBase3DScene();

    var entity = new Entity(new Vector3(1f, 0.5f, 3f))
    {
        new ModelComponent(new CubeProceduralModel().Generate(services)),
        new MotionComponentScript()
    };

    entity.Scene = game.SceneSystem.SceneInstance.RootScene;
}

or

using var game = new Game();

game.Run(start: Start, update: null);

void Start(Scene rootScene, IServiceRegistry services)
{
    // Cherry Pick
    game.SetupBase(); // required, adds scene, graphics comositor, camera
    //game.AddSkybox();
    //game.AddGround();
    game.AddMouseLookCamera();
    game.AddProfiler();

    var entity = new Entity(new Vector3(1f, 0.5f, 3f))
            {
                new ModelComponent(new CubeProceduralModel().Generate(services)),
                new MotionComponentScript()
            };

    entity.Scene = game.SceneSystem.SceneInstance.RootScene;
}

Example 2

Using Update(), game.NewDefaultMaterial() extension.

using (var game = new Game())
{
    var entity = new Entity(new Vector3(1f, 0.5f, 3f));
    var angle = 0f;
    var initialPosition = entity.Transform.Position;

    game.OnInitialize += () => System.Console.WriteLine("Hello, manio143");

    game.Run(start: Start, update: Update);

    void Start(Scene rootScene, IServiceRegistry services)
    {
        game.SetupBase3DScene();

        var model = new CubeProceduralModel().Generate(services);

        model.Materials.Add(game.NewDefaultMaterial());

        entity.Components.Add(new ModelComponent(model));

        entity.Scene = game.SceneSystem.SceneInstance.RootScene;
    }

    void Update(Scene rootScene, IServiceRegistry services, GameTime time)
    {
        angle += 1f * (float)time.Elapsed.TotalSeconds;

        var offset = new Vector3((float)Math.Sin(_angle), 0, (float)Math.Cos(_angle)) * 1f;

        entity.Transform.Position = initialPosition + offset;
    }
}

Let me know what you think 😀.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment