Overview
The camera fade feature provides smooth transitions between scenes or states by fading the screen to black. It supports both screen-space UI and world-space fading methods, automatically selecting the appropriate approach based on the platform.
Setup
- Add the
FadeManager prefab (Assets/Prefabs/Fade/FadeManager.prefab) as a child of your main camera
- Note: This is already parented to the main camera prefab if using the io.kanda.players package
- Configure:
InitialFadeDirection: Initial fade direction (In/Out)
FadeTimeSeconds: Duration of fade transition
FadeOnAwake: Start fading immediately on scene load
ScreenSpaceFadeVisual: UI-based fade visualization
WorldSpaceFadeVisual: Mesh-based fade visualization
Architecture
Core Components
FadeController
The core logic component that handles fade calculations and timing:
public class FadeController : IFadeController
{
public void Initialize(FadeDirection initialDirection, bool startFading)
{
}
public void Update(float deltaTime)
{
}
public void StartFade(FadeDirection direction)
{
}
public bool IsFadeComplete()
{
}
FadeVisual
Interface for implementing fade visualizations:
public interface IFadeVisual
{
void SetOpacity(float opacity);
}
Two built-in implementations are provided:
ScreenSpaceFadeVisual: Uses a UI canvas for traditional displays
WorldSpaceFadeVisual: Uses a mesh with a fade shader for VR/XR platforms
Platform-Specific Implementation
The system automatically chooses between visualization methods based on the platform:
- Screen Space: Uses a UI canvas's alpha for traditional displays
- World Space: Uses a custom shader on a mesh for VR/XR platforms
The FadeManager handles this selection based on the IPlatformInfoService.
Custom Fade Visuals
You can implement custom fade behaviors by:
- Creating a class inheriting from
BaseFadeVisual
- Implementing the
SetOpacity method
- Assigning your visual to the FadeManager
Example:
public class CustomFadeVisual : BaseFadeVisual
{
[SerializeField] private Material _material;
private static readonly int OpacityProperty = Shader.PropertyToID("_Opacity");
public override void SetOpacity(float opacity)
{
_material.SetFloat(OpacityProperty, opacity);
}
}
Usage
Service Integration
Fades can be triggered from any script using the FadeService:
public class FadeExample : MonoBehaviour
{
private IFadeService _fadeService;
private async void Start()
{
_fadeService = AppServiceLocator.Get<IFadeService>();
await _fadeService.Perform(FadeDirection.Out);
await Task.Delay(1000);
await _fadeService.Perform(FadeDirection.In);
}
}
ECS Integration
Example system that fades based on player proximity:
public partial struct ProximityFadeSystem : ISystem
{
public void OnUpdate(ref SystemState state)
{
var playerPosition = SystemAPI.GetSingleton<PlayerTag>()
.GetComponentRO<LocalToWorld>().ValueRO.Position;
foreach (var (trigger, triggerTransform) in
SystemAPI.Query<RefRO<FadeTrigger>, RefRO<LocalToWorld>>())
{
var distance = math.distance(
playerPosition,
triggerTransform.ValueRO.Position);
var fade = AppServiceLocator.Get<IFadeService>();
if (fade.IsComplete() && distance < trigger.ValueRO.FadeDistance)
{
fade.Perform(FadeDirection.Out);
}
else if (fade.IsComplete())
{
fade.Perform(FadeDirection.In);
}
}
}
}
Removal
To disable fading functionality:
- If using the players package: disable the FadeManager in your main camera
- Otherwise: remove the FadeManager GameObject from your scene