riversong code showcase
This commit is contained in:
145
Source/Riversong/Game/Camera/CameraSystem.cs
Normal file
145
Source/Riversong/Game/Camera/CameraSystem.cs
Normal file
@@ -0,0 +1,145 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
[Service(typeof(ICameraProperties))]
|
||||
public class CameraSystem : GameSystem, IInitializable, IUpdatable, ICameraProperties
|
||||
{
|
||||
[InjectService]
|
||||
private GameConfig _gameConfig;
|
||||
|
||||
[InjectService]
|
||||
private IScene _scene;
|
||||
|
||||
private GameConfig.CameraConfig _cameraConfig;
|
||||
|
||||
private CinemachineBrain _cinemachineBrain;
|
||||
|
||||
private CinemachineFollow _cinemachineFollow;
|
||||
|
||||
private Transform _target;
|
||||
|
||||
private float _targetZoom;
|
||||
|
||||
private Vector3? _terrainDragAnchor;
|
||||
|
||||
public CameraSystem(IServiceLocator serviceLocator) : base(serviceLocator)
|
||||
{
|
||||
}
|
||||
|
||||
public float Zoom { get; private set; }
|
||||
|
||||
public UniTask InitializeAsync()
|
||||
{
|
||||
_cameraConfig = _gameConfig.Camera;
|
||||
|
||||
_cinemachineBrain = _scene.MainCamera.GetComponent<CinemachineBrain>();
|
||||
|
||||
_cinemachineFollow = (CinemachineFollow)_scene.CinemachineCamera.GetCinemachineComponent(CinemachineCore.Stage.Body);
|
||||
_target = _cinemachineFollow.FollowTarget;
|
||||
|
||||
Zoom = _targetZoom = _cinemachineFollow.FollowOffset.magnitude;
|
||||
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
var dt = Time.unscaledDeltaTime;
|
||||
|
||||
UpdateZoom(dt);
|
||||
UpdatePosition(dt);
|
||||
UpdateRotation(dt);
|
||||
|
||||
_cinemachineBrain.ManualUpdate();
|
||||
}
|
||||
|
||||
private void UpdateZoom(float dt)
|
||||
{
|
||||
var zoomInput = -1 * Mouse.current.scroll.y.ReadValue();
|
||||
|
||||
_targetZoom += zoomInput * _cameraConfig.ZoomSensitivity;
|
||||
_targetZoom = Mathf.Clamp(_targetZoom, _cameraConfig.ZoomRange.x, _cameraConfig.ZoomRange.y);
|
||||
|
||||
Zoom = Mathf.Lerp(Zoom, _targetZoom, _cameraConfig.ZoomSpeed * dt);
|
||||
|
||||
_cinemachineFollow.FollowOffset = _cinemachineFollow.FollowOffset.normalized * Zoom;
|
||||
}
|
||||
|
||||
private void UpdatePosition(float dt)
|
||||
{
|
||||
var moveInput = Vector3.zero;
|
||||
|
||||
moveInput.x += Keyboard.current.dKey.isPressed ? 1 : 0;
|
||||
moveInput.x += Keyboard.current.aKey.isPressed ? -1 : 0;
|
||||
moveInput.z += Keyboard.current.wKey.isPressed ? 1 : 0;
|
||||
moveInput.z += Keyboard.current.sKey.isPressed ? -1 : 0;
|
||||
|
||||
var right = _target.right;
|
||||
var forward = _target.forward;
|
||||
forward.y = 0;
|
||||
forward.Normalize();
|
||||
|
||||
var normalizedZoom = Mathf.InverseLerp(_cameraConfig.ZoomRange.x, _cameraConfig.ZoomRange.y, Zoom);
|
||||
var moveSpeed = Mathf.Lerp(_cameraConfig.MoveSpeed.x, _cameraConfig.MoveSpeed.y, normalizedZoom);
|
||||
var delta = moveSpeed * dt;
|
||||
|
||||
_target.position += right * (moveInput.x * delta);
|
||||
_target.position += forward * (moveInput.z * delta);
|
||||
|
||||
UpdateDraggingTerrain();
|
||||
}
|
||||
|
||||
private void UpdateDraggingTerrain()
|
||||
{
|
||||
if (!Mouse.current.middleButton.isPressed)
|
||||
{
|
||||
_terrainDragAnchor = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var plane = new Plane(Vector3.up, new Vector3(0, _gameConfig.GeneralSettings.BaseElevation, 0));
|
||||
var ray = _scene.MainCamera.ScreenPointToRay(Mouse.current.position.ReadValue());
|
||||
if (!plane.Raycast(ray, out var enter)) return;
|
||||
|
||||
var hit = ray.GetPoint(enter);
|
||||
if (_terrainDragAnchor == null)
|
||||
{
|
||||
_terrainDragAnchor = hit;
|
||||
return;
|
||||
}
|
||||
|
||||
_target.position += _terrainDragAnchor.Value - hit;
|
||||
}
|
||||
|
||||
private void UpdateRotation(float dt)
|
||||
{
|
||||
var keyboard = Keyboard.current;
|
||||
var rotation = _target.rotation.eulerAngles;
|
||||
var keyboardRotationDelta = Vector2.zero;
|
||||
|
||||
keyboardRotationDelta.x += keyboard.eKey.isPressed ? 1 : 0;
|
||||
keyboardRotationDelta.x += keyboard.qKey.isPressed ? -1 : 0;
|
||||
keyboardRotationDelta.y += keyboard.rKey.isPressed ? 1 : 0;
|
||||
keyboardRotationDelta.y += keyboard.fKey.isPressed ? -1 : 0;
|
||||
|
||||
rotation.y += keyboardRotationDelta.x * _cameraConfig.KeyboardRotationSpeed.x * dt;
|
||||
rotation.x -= keyboardRotationDelta.y * _cameraConfig.KeyboardRotationSpeed.y * dt;
|
||||
|
||||
if (keyboard.leftAltKey.isPressed)
|
||||
{
|
||||
var mouseDelta = Mouse.current.delta;
|
||||
|
||||
rotation.x += mouseDelta.y.ReadValue() * _cameraConfig.MouseRotationSpeed.y * dt;
|
||||
rotation.y += mouseDelta.x.ReadValue() * _cameraConfig.MouseRotationSpeed.x * dt;
|
||||
}
|
||||
|
||||
rotation.x = Mathf.Clamp(rotation.x, _cameraConfig.PitchRange.x, _cameraConfig.PitchRange.y);
|
||||
|
||||
_target.forward = Quaternion.Euler(rotation) * Vector3.forward;
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Source/Riversong/Game/Camera/ICameraProperties.cs
Normal file
7
Source/Riversong/Game/Camera/ICameraProperties.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
public interface ICameraProperties
|
||||
{
|
||||
float Zoom { get; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user