Untitled
unknown
csharp
a month ago
6.1 kB
14
Indexable
using System;
using System.Linq;
using System.Runtime.Serialization;
[TypeUid(7008)]
public class GameCameraComponent : ExternInitComponent
{
[Export] public NodePath targetPath;
[IgnoreDataMember] public Spatial target;
[Export] public Camera CameraObject => CameraSwitch.camera;
[Export] public float smoothing = 5f;
[Export] public float rotSmoothing = 3f;
[Export] public float MoveSpeed = 3f;
[Export] public float maxDistance = 9f;
[Export] public NodePath defaultPositionPath;
[IgnoreDataMember] public Spatial defaultPosition;
[Export] public NodePath connectNodePath;
[IgnoreDataMember] public Spatial connectNode;
[Export] int GroundLayer;
[Export] public bool Follow;
[Export] public NodePath cameraRigidPath;
[IgnoreDataMember] public RigidBody transform;
public Node nodeOwner => (Node)this.ownerEntity.GetComponent<RealNodeOwnerComponent>().EntityNode;
private CameraControlSwitchComponent cacheComponent;
[IgnoreDataMember] public CameraControlSwitchComponent CameraSwitch
{
get
{
if(cacheComponent == null)
cacheComponent = this.ownerEntity.GetComponent<CameraControlSwitchComponent>();
return cacheComponent;
}
}
// offset нам больше не нужен, мы будем использовать локальную позицию defaultPosition
public override void ExternalInitialize()
{
base.ExternalInitialize();
defaultPosition = nodeOwner.GetNode(defaultPositionPath) as Spatial;
transform = nodeOwner.GetNode<RigidBody>(cameraRigidPath);
connectNode = nodeOwner.GetNode<Spatial>(connectNodePath);
GroundLayer = LayerMask.GetMask("ground");
this.ownerEntity.GetComponent<RealNodeOwnerComponent>().EntityNode.Hooks.RegisterHook(
GodotCommon.Starter.HookController.HookMethod.PhysicsProcess,
0,
FixedUpdate, this.instanceId
);
}
protected override void OnAdded(ECSEntity entity)
{
base.OnAdded(entity);
if(string.IsNullOrEmpty(targetPath))
{
var firstObj = this.ownerEntity.ECSWorldOwner.entityManager.SearchGraph(null, new Type[]{typeof(PhysicsComponent)}).ToHashSet().FirstOrDefault();
if(firstObj!=null)
{
target = firstObj.GetComponent<PhysicsComponent>().Rigidbody;
}
}
else
{
target = nodeOwner.GetNode(targetPath) as Spatial;
}
}
public void FixedUpdate(float dt)
{
if (CameraSwitch.cameraMode == CameraControlSwitchComponent.CameraMode.Target && target != null)
{
if(CameraSwitch.camera.GetParent() != this.connectNode)
{
CameraSwitch.camera.ChangeParent(this.connectNode);
}
//float dt = TimeService.deltaTime;
// 1. ПЛАВНО СЛЕДУЕМ ЗА ПОЗИЦИЕЙ
transform.GlobalPosition = Vector3U.Lerp(transform.GlobalPosition, target.GlobalPosition, smoothing * dt);
// 2. ПЛАВНО СЛЕДУЕМ ЗА ПОВОРОТОМ (Учитываем нормализацию из-за возможного масштаба)
Quat currentRot = new Quat(transform.GlobalTransform.basis).Normalized();
Quat targetRot = new Quat(target.GlobalTransform.basis).Normalized();
Quat newRot = currentRot.Slerp(targetRot, rotSmoothing * dt).Normalized();
Transform t = transform.GlobalTransform;
t.basis = new Basis(newRot);
transform.GlobalTransform = t;
float LeftTurnInput = true ? Input.IsKeyPressed((int)KeyList.Q) ? 1f : 0f : 0f;
float RightTurnInput = true ? Input.IsKeyPressed((int)KeyList.E) ? 1f : 0f : 0f;
// Вычисляем изменение высоты
float heightDirection = RightTurnInput - LeftTurnInput;
if (Mathf.Abs(heightDirection) > 0.01f)
{
// Меняем ЛОКАЛЬНУЮ позицию, чтобы камера двигалась вверх/вниз относительно текущего наклона танка
Vector3 localPos = defaultPosition.Translation;
localPos.y += MoveSpeed * heightDirection * dt;
defaultPosition.Translation = localPos;
}
// 4. ЛОГИКА СТОЛКНОВЕНИЙ И ПЕРЕМЕЩЕНИЕ КАМЕРЫ
float distanceOffset = 0.5f; // Отступ от стены, чтобы камера не проваливалась в текстуры
RaycastHit hit;
Vector3 desiredGlobalPos = defaultPosition.GlobalPosition;
if (Physics.Linecast(target.GlobalPosition, desiredGlobalPos, out hit, GroundLayer, QueryTriggerInteraction.Ignore))
{
// Вычисляем вектор от точки попадания к таргету, чтобы немного отдвинуть камеру от стены
Vector3 dirToTarget = (target.GlobalPosition - hit.point).Normalized();
Vector3 adjustedPos = hit.point + (dirToTarget * distanceOffset);
CameraObject.GlobalPosition = Vector3U.Lerp(CameraObject.GlobalPosition, adjustedPos, smoothing * dt);
}
else
{
// Путь свободен, летим к идеальной позиции
CameraObject.GlobalPosition = Vector3U.Lerp(CameraObject.GlobalPosition, desiredGlobalPos, smoothing * dt);
}
// 5. КАМЕРА ВСЕГДА СМОТРИТ НА ЦЕЛЬ
CameraObject.LookAt(target.GlobalPosition, Vector3.Up);
}
}
protected override void OnRemoved(ECSEntity entity)
{
base.OnRemoved(entity);
this.ownerEntity.GetComponent<RealNodeOwnerComponent>().EntityNode.Hooks.Reset(this.instanceId);
}
}Editor is loading...