Skip to content

Commit

Permalink
[website] Add docs about UniTask, ExceptionHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
hadashiA committed Jan 31, 2021
1 parent 1d0fba3 commit a75c85b
Show file tree
Hide file tree
Showing 24 changed files with 294 additions and 466 deletions.
21 changes: 19 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The extra fast DI (Dependency Injection) library running on Unity Game Engine.
- Flexible scoping
- Application can freely create nested Lifetime Scope with any async way for you like.
- Pre IL Code generation optimization mode
- UniTask Integration
- ECS Integration *beta*

## Performance
Expand All @@ -30,8 +31,6 @@ The extra fast DI (Dependency Injection) library running on Unity Game Engine.

### GC Alloc Result Example



![](./website/static/img/gc_alloc_profiler_result.png)

![](./website/static/img/screenshot_profiler_vcontainer.png)
Expand Down Expand Up @@ -232,6 +231,24 @@ using (LifetimeScope.Enqueue(builder =>
}
```

## UniTask

```csharp
public class FooController : IAsyncStartable
{
public async UniTask StartAsync(CancellationToken cancellation)
{
await LoadSomethingAsync(cancellation);
await ...
...
}
}
```

```csharp
builder.RegisterEntryPoint<FooController>(Lifetime.Scoped);
```

## Documentation

Visit [vcontainer.hadashikick.jp](https://vcontainer.hadashikick.jp) to view the full documentation.
Expand Down
5 changes: 5 additions & 0 deletions website/.idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions website/.idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions website/.idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions website/.idea/website.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 20 additions & 1 deletion website/docs/about/what-is-vcontainer.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ The extra fast DI (Dependency Injection) for Unity Game Engine. "V" means making
- [Flexible scoping](../scoping/lifetime-overview)
- Application can freely create nested Lifetime Scope with any async way for you like.
- [Pre IL Code generation optimization mode](../optimization/codegen)
- [ECS Integration](../integration/ecs) *beta*
- [UniTask Integration](../integrations/unitask)
- [ECS Integration](../integrations/ecs) *beta*

## DI + Inversion of Control for Unity

Expand Down Expand Up @@ -212,6 +213,24 @@ using (LifetimeScope.Enqueue(builder =>
}
```

## UniTask

```csharp
public class FooController : IAsyncStartable
{
public async UniTask StartAsync(CancellationToken cancellation)
{
await LoadSomethingAsync(cancellation);
await ...
...
}
}
```

```csharp
builder.RegisterEntryPoint<FooController>(Lifetime.Scoped);
```

## Getting Started

- [Installation](../getting-started/installation)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: Integrating with ECS (beta)
title: ECS (beta)
---

VContainer supports integration between Unity's ECS (Entity Component System) and regular C# World.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,34 @@
---
title: Dispatching Unity's Lifecycle events
title: Plain C# Entry point
---

VContainer has own PlayerLoop sub systems.
VContainer allows plain C# to be the starting point for application processing.
Using it instead of MonoBehaviour, which has a lot of features, can help you build a simple control flow.

```csharp
clas FooController : IStartable
{
void IStartable.Start()
{
// Do something ...
}
}
```

```csharp
builder.RegisterEntryPoint<FooController>(Lifetime.Scoped);
```

See [register](./docsregistering/register-type#register-lifecycle-marker-interfaces)

VContainer does this with its own PlayerLoopSystem.

If you register a class that implements the marker interface, it will be scheduled in Unity's PlayerLoop cycle.

Since it uses PlayerLoopSystem, it works even if you register at any time (e.g: `IStartable` etc)


The following interfaces and timings are available.
## Available interfaces

| VContaienr entry point | Timing |
|:--------------------------------------|:----------------------------------|
Expand All @@ -33,3 +52,25 @@ And
:::note
[Unity - Manual: Order of Execution for Event Functions](https://docs.unity3d.com/Manual/ExecutionOrder.html)
:::

## Handle of the exception that was not caught

On the application side, exceptions thrown in processes such as Start() and Tick() cannot be caught outside.

By default, VContainer logs unhandled exceptions as `UnityEngine.Debug.LogException`.
As another option, you can register a callback for each LifetimeScope.

```csharp
builder.RegisterEntryPointExceptionHandler(ex =>
{
// ...
});
```

:::caution
Default error logging will be skipped if you are using the RegisterEntryPointExceptionHandler.
:::

## UniTask

If you are using UniTask, you can use `IAsyncStartable`. see also [UniTask Integration](../integrations/unitask)
62 changes: 62 additions & 0 deletions website/docs/integrations/unirx.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: UniRx
---

[UniRx](https://github.com/neuecc/UniRx) is an Rx (Reactive Extension) library optimized for Unity.

Here is an example of combining VContainer entry points with UniRx.

```csharp
public class FooController : IStartable, IDisposable
{
readonly CompositeDisposable disposable = new CompositeDisposable;

void IStartable.Start()
{
fooObservable
.Subscribe(_ => /* Do something */)
.AddTo(disposable)
}

void IDisposable.Dispose() => disposable.Dispose();
}
```

If you want to create a short hand like `AddTo(this)`, you can create an extension method like this:
```csharp
public class ControllerBase : IDisposable
{
readonly CompositeDisposable disposable = new CompositeDisposable;

void IDisposable.Dispose() => disposable.Dispose();

public void AddDisposable(IDisposable disposable)
{
disposables.Add(disposable);
}
}

public static class DisposableExtensions
{
public static T AddTo<T>(this T disposable, Heipu.Presentation.Controllers.ControllerBase controller)
where T: IDisposable
{
controller.AddDisposable(disposable);
return disposable;
}
}
```

This can be used as follows:

```csharp
public class FooController : ControllerBase, IStartable
{
void IStartable.Start()
{
someObservable
.Subscribe(...)
.AddTo(this);
}
}
```
75 changes: 75 additions & 0 deletions website/docs/integrations/unitask.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
title: UniTask
---

[UniTask](https://github.com/Cysharp/UniTask) is a library that brings fast and powerful async/await to the Unity world.

If you have the `com.cysharp.unitask` package installed in your project, the following features will be enabled.

## IAsyncStartable

We can create an entry point for the async UniTask.

```csharp
public class FooController : IAsyncStartable
{
public async UniTask StartAsync(CancellationToken cancellation)
{
await LoadSomethingAsync(cancellation);
await ...
...
}
}
```

By creating a class like the one above and Registering it, the UniTask of StartAsync will be executed automatically.

```csharp
builder.RegisterEntryPoint<FooController>(Lifetime.Scoped);
```

For more information about RegisterEntryPoint, please check [here](../integrations/entrypoint).

### StartAsync() timing

The only async interface provided by VContainer is IAsyncStartable.
UniTask can control the execution timing within the async method.

If you want to schedule the process at different times, you can use UniTask's PlayerLoopTiming.

```csharp
await UniTask.Yield(PlayerLoopTiming.FixedUpdate);
```

See https://github.com/Cysharp/UniTask#playerloop

### Exception Handling

- Within the async method, try/catch can be used.
- We can use `UniTaskScheduler.UnobservedTaskException` event.
- Alternatively, if you want to register a separate error handler for each LifetimeScope, use:
- `builder.RegisterEntryPointExceptionHandler(ex => ..)`
- See [Entry point](./entrypoint) section for more information.

### CancellationToken

The argument of StartAsync will be a cancellationToken.

This cancellationToken will be canceled when the LifetimeScope is destroyed.

### Async asset loading

UniTask supports the ability to load assets and scenes asynchronously.
This is useful when used with LifetimeScope.Enqueue* in VContainer.

```csharp
var extraAsset = await Addressables.LoadAssetAsync<ExtraAsset>(key);

using (LifetimeScope.EnqueueParent(parentScope))
using (LifetimeScope.Enqueue(builder => builder.RegisterInstance(extraAsset))
{
await SceneManager.LoadSceneAsync("AdditiveScene");
}
```

See [Scoping](../scoping/generate-child-via-scene) secion for more information.
8 changes: 8 additions & 0 deletions website/docs/registering/register-monobehaviour.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,11 @@ builder.RegisterComponentInHierarchy<YourBehaviour>();
builder.RegisterComponentFromNewPrefab(prefab, Lifetime.Scoped);
builder.RegisterComponentOnNewGameObject<YourBehaviour>(Lifetime.Scoped, "name");
```

## Execute only Inject for MonoBehaviour on the scene

In VContainer, objects that are not explicitly registered will not be injected. Therefore, execute Register for the object you want to inject.

If you want to run **"Inject Only"** into MonoBehaviour, you can do so by inserting GameObject in the `autoInjectGameObject` field of LifetimeScope.

![](./assets/screenshot_auto_inject_gameobjects.png)
2 changes: 1 addition & 1 deletion website/docs/registering/register-scriptable-object.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: ScriptableObject Integration
title: Register ScriptableObject
---

It is useful to register the setting information saved as ScriptableObject Asset as follows.
Expand Down
16 changes: 15 additions & 1 deletion website/docs/registering/register-type.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: Register Type
title: Register Plain C# Type
---

There are various ways to use Register.
Expand Down Expand Up @@ -122,6 +122,16 @@ builder.RegisterEntryPoint<GameController>(Lifetime.Singleton);
this is similar to `Register<GameController>(Lifetime.Singleton).AsImplementedInterfaces()`
:::

If you want to customize the exception handling for entry points, you can register a callback with the following.

```csharp
builder.RegisterEntryPointExceptionHandler(ex =>
{
UnityEngine.Debug.LogException(ex);
// Additional process ...
});
```

If you have multiple EntryPoints, you have the option to use the following declaration as grouping.

```csharp
Expand All @@ -130,6 +140,7 @@ builder.UseEntryPoints(Lifetime.Scoped, entryPoints =>
entryPoints.Add<ScopedEntryPointA>();
entryPoints.Add<ScopedEntryPointB>();
entryPoints.Add<ScopedEntryPointC>().AsSelf();
entryPoints.OnException(ex => ...)
});
```

Expand All @@ -139,8 +150,11 @@ This is the same as:
builder.RegisterEntryPoint<ScopedEntryPointA>(Lifetime.Scoped);
builder.RegisterEntryPoint<ScopedEntryPointB>(Lifetime.Scoped);
builder.RegisterEntryPoint<ScopedEntryPointC>(Lifetime.Scoped).AsSelf();
builder.RegisterEntryPointExceptionHandler(ex => ...);
```

See [Plain C# Entry point](../integrations/entrypoint) section for more information.

## Register instance

```csharp
Expand Down
Loading

0 comments on commit a75c85b

Please sign in to comment.