Protfolio-Emanuel-Polsky / Assets / _Project / Code / Player / Camera / SetCameraTransformSystem.cs
SetCameraTransformSystem.cs
Raw
using Unity.Burst;
using Unity.Entities;
using UnityEngine;
using GarmentButton.PlayerTags;
using Unity.Transforms;
using Unity.Physics;
using GarmentButton.PhysicFillters;
using Unity.Mathematics;

namespace GarmentButton.CameraGeneral
{
    public partial struct SetCameraTransformSystem : ISystem, ISystemStartStop
    {


        public void OnCreate(ref SystemState state)
        {
            state.RequireForUpdate<PlayerTag>();
            state.RequireForUpdate<CameraReferenceProperty>();
            state.RequireForUpdate<CameraRotationProperties>();
            state.RequireForUpdate<CameraPositionProperties>();
        }

        public void OnStartRunning(ref SystemState state)
        {
            var playerEntity = SystemAPI.GetSingletonEntity<PlayerTag>();
            var playerTransform = SystemAPI.GetComponent<LocalTransform>(playerEntity);
            foreach (var (cameraProperty, basedRotation, offset) in SystemAPI.Query<RefRW<CameraReferenceProperty>, RefRW<BaseRotation>, RefRW<CameraOffestFromPlayer>>())
                offset.ValueRW.Value = (float3)cameraProperty.ValueRO.Transform.Value.position - playerTransform.Position;
        }

        public void OnStopRunning(ref SystemState state)
        {
        }
        public void OnUpdate(ref SystemState state)
        {
            var playerEntity = SystemAPI.GetSingletonEntity<PlayerTag>();
            var playerTransform = SystemAPI.GetComponentRO<LocalTransform>(playerEntity);

            foreach (var (camera, cameraRotation, cameraPosition, playerScreenPosition, directionToPlayer) in SystemAPI.Query<RefRW<CameraReferenceProperty>, RefRW<CameraRotationProperties>, RefRW<CameraPositionProperties>, RefRW<ScreenPositionPlayer>, RefRW<CameraDirectionToPlayer>>())
            {
                cameraRotation.ValueRW.Value = camera.ValueRO.Transform.Value.rotation;
                cameraPosition.ValueRW.Value = camera.ValueRO.Transform.Value.position;
                playerScreenPosition.ValueRW.Value = camera.ValueRO.Value.Value.WorldToViewportPoint(playerTransform.ValueRO.Position);
                directionToPlayer.ValueRW.Value = playerTransform.ValueRO.Position - cameraPosition.ValueRO.Value;

            }

            foreach (var item in  SystemAPI.Query<RefRO<FollowPlayerObjectTag>>())
            {
                item.ValueRO.Value.Value.SetPositionAndRotation(playerTransform.ValueRO.Position, playerTransform.ValueRO.Rotation);
            }
        }
    }
    [UpdateAfter(typeof(SetCameraTransformSystem))]
    [BurstCompile]
    public partial struct CheckSomeBetweenCameraAndPlayerSystem : ISystem
    {

        [BurstCompile]
        public void OnCreate(ref SystemState state)
        {
            state.RequireForUpdate<PhysicsWorldSingleton>();
            state.RequireForUpdate<CameraPositionProperties>();
            state.RequireForUpdate<CameraRotationProperties>();
            state.RequireForUpdate<CameraDirectionToPlayer>();
            state.RequireForUpdate<BaseRotation>();
            state.RequireForUpdate<WantedRotationCamera>();
            state.RequireForUpdate<PlayerTag>();
            state.RequireForUpdate<LocalTransform>();
        }
        [BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
            var playerEntity = SystemAPI.GetSingletonEntity<PlayerTag>();
            var playerTransform = SystemAPI.GetComponent<LocalTransform>(playerEntity);

            var physicsWorld = SystemAPI.GetSingleton<PhysicsWorldSingleton>();
            
            foreach (var (position, rotation, baseRotation, desireRotation, shouldRotate, offset) in SystemAPI.Query<RefRO<CameraPositionProperties>, RefRO<CameraRotationProperties>, RefRO<BaseRotation>, RefRW<WantedRotationCamera>, EnabledRefRW<WantedRotationCamera>, RefRO<CameraOffestFromPlayer>>().WithPresent<WantedRotationCamera>())
            {
                var startPosition = playerTransform.Position + offset.ValueRO.Value;
                var endPosition = startPosition + (-offset.ValueRO.Value * 0.9f);
                Debug.DrawLine(startPosition, endPosition, Color.green);

                quaternion wantedRotation;

                var rayCastInput = new RaycastInput()
                {
                    Start = startPosition,
                    End = endPosition,
                    Filter = new CollisionFilter
                    {
                        BelongsTo = (uint)CollisionLayer.Defualt,
                        CollidesWith = (uint)(CollisionLayer.Ground)
                    }
                };
                if (physicsWorld.CastRay(rayCastInput, out var hit))
                {
                    var angle = math.radians(45);
                    //var angle = 45 * Time.deltaTime;
                    quaternion rotationX = quaternion.RotateX(angle);
                    wantedRotation = math.mul(rotationX, baseRotation.ValueRO.Value);

                }
                else
                {
                    wantedRotation = baseRotation.ValueRO.Value;
                }

                wantedRotation = math.slerp(rotation.ValueRO.Value, wantedRotation, 10f *  Time.deltaTime);

                if (!Approximately(wantedRotation, rotation.ValueRO.Value))
                {
                    var wantedRotationClearer = RoundSmallValuesToZero(wantedRotation);
                    desireRotation.ValueRW.Value = RoundSmallValuesToZero(wantedRotationClearer);
                    shouldRotate.ValueRW = true;
                }
                else
                {
                    shouldRotate.ValueRW = false;
                }

            }
        }
        public bool Approximately(quaternion q1, quaternion q2, float epsilon = 1e-5f)
        {
            // Calculate the dot product between the two quaternions
            float dot = math.dot(q1.value, q2.value);

            // Quaternions are approximately equal if their dot product is close to 1
            return math.abs(dot - 1f) < epsilon;
        }

        public quaternion RoundSmallValuesToZero(quaternion q, float threshold = 1e-5f)
        {
            return new quaternion(
                math.abs(q.value.x) < threshold ? 0f : q.value.x,
                math.abs(q.value.y) < threshold ? 0f : q.value.y,
                math.abs(q.value.z) < threshold ? 0f : q.value.z,
                math.abs(q.value.w) < threshold ? 0f : q.value.w
            );
        }

    }

    [UpdateAfter(typeof(CheckSomeBetweenCameraAndPlayerSystem))]
    public partial struct RotateCameraBased : ISystem
    {

        public void OnCreate(ref SystemState state)
        {
            var query = SystemAPI.QueryBuilder().WithAll<CameraReferenceProperty, WantedRotationCamera>().Build();
            state.RequireForUpdate(query);
        }
        public void OnUpdate(ref SystemState state)
        {
            foreach (var (camera, rotation) in SystemAPI.Query<CameraReferenceProperty, RefRO<WantedRotationCamera>>())
            {
                camera.Transform.Value.rotation = rotation.ValueRO.Value;
            }
        }
    }
}