crazytuzi / UnrealCSharp

UnrealCSharp, based on .NET 8 (Mono), is a C# programming plugin for UE.
https://unrealcsharp.github.io/
MIT License
498 stars 76 forks source link

[BUG] ReceiveTick 里,计算 FVectorA - FVectorB,会崩溃 #430

Open cocochengang opened 2 days ago

cocochengang commented 2 days ago

在 ReceiveTick 里,计算 FVectorA - FVectorB,会崩溃:

[2024.10.20-17.44.01:021][709]LogWindows: Error: [Callstack] 0x00007ffc531ce3f0 UnrealEditor-UnrealCSharp.dll!TClassBuilder<UE::Math::TVector<double>,1>::MinusImplementation() [F:\UEPrjs\SoulMecha\BoD\Plugins\UnrealCSharp\Source\UnrealCSharp\Public\Binding\Class\TClassBuilder.inl:112]
[2024.10.20-17.44.01:021][709]LogWindows: Error: [Callstack] 0x00007ffc531a8696 UnrealEditor-UnrealCSharp.dll!TFunctionHelper<TTuple<UE::Math::TVector<double>,std::tuple<UE::Math::TVector<double> const &,UE::Math::TVector<double> const &> > >::Call<UE::Math::TVector<double> (__cdecl*)(UE::Math::TVector<double> const &,UE::Math::TVector<double> const &),0,1>() [F:\UEPrjs\SoulMecha\BoD\Plugins\UnrealCSharp\Source\UnrealCSharp\Public\Binding\Function\TFunctionHelper.inl:35]
[2024.10.20-17.44.01:021][709]LogWindows: Error: [Callstack] 0x00007ffc531cae90 UnrealEditor-UnrealCSharp.dll!TFunctionBuilder<UE::Math::TVector<double> (__cdecl*)(UE::Math::TVector<double> const &,UE::Math::TVector<double> const &),&TClassBuilder<UE::Math::TVector<double>,1>::MinusImplementation>::Invoke() [F:\UEPrjs\SoulMecha\BoD\Plugins\UnrealCSharp\Source\UnrealCSharp\Public\Binding\Function\TFunctionBuilder.inl:59]
crazytuzi commented 1 day ago

附上具体测试C#代码

cocochengang commented 1 day ago

UE:5.4.4 UECSharp:v0.5.0

实现角色移出一个相对范围后,镜头跟着移动的功能。 image

using System;
using System.Threading;
using System.Threading.Tasks;
using Script.CoreUObject;
using Script.Dynamic;
using Script.Engine;

namespace Script.Game.Blueprints.Characters
{
    [Override]
    public partial class BP_Hero_C
    {
        // private CancellationTokenSource TokenSource;
        [UProperty, EditAnywhere, Category("Camera Movement")]
        protected bool LimitInRect { get; set; } = true;

        [UProperty, EditAnywhere, Category("Camera Movement")]
        protected FVector2D InRect { get; set; } = new(1.6*100, 3*100);

        [UProperty, EditAnywhere, Category("Camera Movement")]
        protected float TargetLength { get; set; } = 1500;

        /*
        withMinMaxXY = false;
        minX:number = 0;
        maxX:number = 0;
        minY:number = 0;
        maxY:number = 0;
        targetPitch = -10;
        targetLength = 700; 
        */

        protected BP_Hero_C(){ }

        [Override]
        public override void ReceiveBeginPlay(){
            base.ReceiveBeginPlay();
            SpringArm.bDoCollisionTest = false;
        }

        [Override]
        public override void ReceiveTick(float DeltaSeconds){
            base.ReceiveTick(DeltaSeconds);

            LocCamera();
        }

        protected void LocCamera(){
            var newLoc = SpringArm.K2_GetComponentLocation();
            var targetLoc = K2_GetActorLocation();

            if (LimitInRect){
                // 直接减会有异常: targetLoc - newLoc
                var deltaLoc = targetLoc - newLoc;
                var deltaLocX = deltaLoc.X;
                var deltaLocY = deltaLoc.Y;

                // var deltaLocX = targetLoc.X - newLoc.X;
                // var deltaLocY = targetLoc.Y - newLoc.Y;

                var deltaX = Math.Abs(deltaLocX);
                var deltaY = Math.Abs(deltaLocY);
                if (deltaX > GetRectX()){
                    var dir = deltaLocX > 0 ? 1 : -1;
                    newLoc.X = targetLoc.X - GetRectX() * dir;
                }
                if (deltaY > GetRectY()){
                    var dir = deltaLocY > 0 ? 1 : -1;
                    newLoc.Y = targetLoc.Y - GetRectY() * dir;
                }

                newLoc.Z = targetLoc.Z;
            }
            else{
                newLoc = targetLoc;
            } 

            /*
                if(this.withMinMaxXY){
                    newLoc.X = Clamp(newLoc.X,this.minX,this.maxX);
                    newLoc.Y = Clamp(newLoc.Y,this.minY,this.maxY);
                }

                // 更改俯仰角
                let currRot = this.camHolder.K2_GetComponentRotation();
                if(Math.abs(currRot.Pitch - this.targetPitch)>0.2){
                    currRot.Pitch = LerpFloat(currRot.Pitch,this.targetPitch,0.05);
                    this.camHolder.K2_SetWorldRotation(currRot,false,undefined,false);
                } 
             */
            var hitResult = new FHitResult();
            SpringArm.K2_SetWorldLocation(newLoc,false,ref hitResult,false);

            var currLen = SpringArm.TargetArmLength;
            if (Math.Abs(currLen - TargetLength) > 1){
                SpringArm.TargetArmLength = float.Lerp(currLen,TargetLength,0.02f);
            }
        }

        double GetRectX(){
            return InRect.X * TargetLength / 1000;
        }

        double GetRectY(){
            return InRect.Y * TargetLength / 1000;
        }

        [Override]
        public override void ReceiveEndPlay(EEndPlayReason EndPlayReason)
        {
            // TokenSource.Cancel();
            base.ReceiveEndPlay(EndPlayReason);
        }
    }
}

很容易出问题: image

LogUnrealCSharp: Error: Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance of an object
   at Script.Game.Blueprints.Characters.BP_Hero_C.LocCamera() in F:\UEPrjs\SoulMecha\BoD\Script\Game\BoD\Blueprints\Characters\BP_Hero_C.cs:line 55
   at Script.Game.Blueprints.Characters.BP_Hero_C.ReceiveTick(Single DeltaSeconds) in F:\UEPrjs\SoulMecha\BoD\Script\Game\BoD\Blueprints\Characters\BP_Hero_C.cs:line 45

image