Open cocochengang opened 2 days ago
附上具体测试C#代码
UE:5.4.4 UECSharp:v0.5.0
实现角色移出一个相对范围后,镜头跟着移动的功能。
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);
}
}
}
很容易出问题:
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
在 ReceiveTick 里,计算 FVectorA - FVectorB,会崩溃: