003_MyMOBA_PawnFeignDeathPhysics

-----------------------------2015.8.9---------------------李明阳---------------------

 

MyMOBAPawn的刚体效果:

MOBAHero的兔子角色因为形体不同于人体,角色倒地后重新站起来的视觉效果不易测试,下面的代码测试部分是在SwordGame项目SwordPlayer中完成。

Mesh转换刚体代码段:

UDN平台游戏的AI被玩家Kill后进入物理状态,经过LifeSpan的时间后消失,但是UDN平台游戏的Pawn没有任何Controller。

UTGame的Pawn在被Kill后进入物理状态,ABC的Pawn在被Kill后进入物理状态,它们的逻辑都差不多,只是UTGame逻辑更多。

为了简化,直接复制UDN平台AI进入物理状态的代码:

UTGame玩家按“F ”后角色倒地,Fire后角色站起来,看起来比较自然。按照UTPawn的代码方式定义UDKMOBAHeroPawn,把上面的代表放入函数PlayFeignDeath()

按ABC角色物理效果做好相应设置后,按下F后,角色倒地,角色转换为刚体后,位置回到了玩家的出生点。在ABC和UDN平台中,这种转换方式用在AIPawn上没有什么问题,在MyMOBA的项目中角色转为刚体后却回到了出生点。SetLocation不能解决这个问题。

ABC和UDN平台都不行,回到UTGame中分析代码;Pawn假装倒地设置了一个变量“bFeigningDeath”,通过查找这个变量,在UTPlayerController中有这样一个函数Mesh.SetRBPosition(),通过测试这个函数的确起作用。

最终UDKMOBAHeroPawn转换成刚体后的代码:

Actor和Component数组是两个不同的部分,Component通过Add(Attach)到Actor,类似于“父子关系”,通过Remove移除,SetLocation仅作用在Actor上。

 

if (bFeigningDeath)

        Mesh.MinDistFactorForKinematicUpdate = 0.0;

        Mesh.ForceSkelUpdate();

        Mesh.SetTickGroup(TG_PostAsyncWork);

        CollisionComponent = Mesh;

        CylinderComponent.SetActorCollision(false, false);

        Mesh.SetActorCollision(true, false);

        Mesh.SetTraceBlocking(true, true);

        SetPawnRBChannels(true);

        SetPhysics(PHYS_RigidBody);

        Mesh.PhysicsWeight = 1.f;

        if (Mesh.bNotUpdatingKinematicDueToDistance)

        {

            Mesh.UpdateRBBonesFromSpaceBases(true, true);

        }

        Mesh.PhysicsAssetInstance.SetAllBodiesFixed(false);

        Mesh.bUpdateKinematicBonesFromAnimation = false;

        Mesh.WakeRigidBody();

        //同步RB组件的Position和Mesh的Position

        Mesh.SetRBPosition(Mesh.GetPosition());

 

Pawn倒地后站起来:

UTPawn倒地后,玩家开火Pawn会再次站起来,按照UTPawn的代码,Controller.Fire→Pawn.Fire。

重写UDKMOBAHeroPawn::StartFire

simulatedfunctionStartFire(byteFireModeNum)

{

    // firing cancels feign death

    if (bFeigningDeath)

    {

        //ComeFromfire用来判断是F键还是StartFire在调用StartFireFeignDeath();

        ComeFromfire = true;

        FeignDeath();

    }

    else

    {

        Super.StartFire(FireModeNum);

    }

}

 

如果是StartFier调用角色假装倒地,角色就站起来,代码如下:

        //碰撞组件改为CylinderComponent

        CollisionComponent = CylinderComponent;

        //Consolcomand::Show Collision时显示CylinderComponent

        CylinderComponent.SetActorCollision(true, true);

        // don't need collision events anymore

        Mesh.SetNotifyRigidBodyCollision(false);

        // don't allow player to move while animation is in progress

        //SetPhysics(PHYS_None);

        Mesh.PhysicsWeight = 0.f;

 

        SetPawnRBChannels(FALSE);

        if (Physics == PHYS_RigidBody)

        {

            setPhysics(PHYS_Falling);

        }

角色站起来动作自然:

UTPawnPlayFeignDeath()函数else部分,(在MOBA项目中暂不需要,略过)

 

MyMOBAHerPawn ::StopFire

当角色倒地后,StarFire重新站起来,加入条件屏蔽StopFire重新生成Pawn

    if(Pawn == None)

    {

        SwitchTeam();

        SelectDemoGuyHero();

    }

 

 

完善角色物理状态:

         虽然按上面的逻辑,角色物理状态能正常州切换,但是有一点很不好,从站立姿势切换成刚体,第一次切换时效果还算可以,第二次切换时,角色要么会从地上弹起来,要么掉到地面下,要么Die。为了解决这个无法接受的Bug,我几乎耗完了一天的时间调试代码。最后得出这样一个原因:进入物理状态时,骨骼刚体间的碰撞比较强烈如果Box或Sphere之间有穿插,角色被撕扯得厉害。第二次进入刚体时角色会弹起来,原因正是MeshPhysics和CyllinderComponent发生了碰撞,因为Mesh始终放在Cyllinder中间,它们有穿插,碰撞过程中Mesh就会从Cyllinder中弹出去。

         知道了原因,解决两个碰撞组件交换的问题。通过改变CollisionComponent的值配合SetActorCollision(),在视觉效果上能达到理想的结果,但是在刚体运算过程中Mesh还是会弹。直接屏蔽掉CyllinderComponent(CyllinderComponent去掉会有影响,不能去掉),角色只用Mesh来碰撞,OK角色不会弹,但是物理效果仍不是十分地好,但是已经可以了,,但是没有CyllinderComponent处理复杂碰撞时难保一切正常。

         第二天,脑袋稍微清晰一些,既然第一次倒地能正常,第二次不正常。第一次倒地后Mesh的Pyhsics被激活了,如果第二次倒地重新激活,Mesh和Cyllinder如同第一次不会弹。查看相关函数或变量,找到这样一个函数:Mesh.SetHasPhysicsAssetInstance(true,false);经过测试起作用了,效果很好,角色在跑的过程中突然倒下在运动方向上有惯性,而且不用屏蔽CyllinderComponent。

 

在不改变CyllinderComponent为常规碰撞组件情况下,必要时启动Physics

进入刚体时代碰撞转换码逻辑:

CylinderComponent.SetActorCollision(false, false);

CollisionComponent = Mesh //关掉这个,相机目标不是Mesh而是Actor(玩家倒下时相机不会抖一下)

Mesh.SetActorCollision(true, true);

Mesh.SetHasPhysicsAssetInstance(true,false);

玩家站起来时碰撞转换代码逻辑:

CollisionComponent = CylinderComponent;

CylinderComponent.SetActorCollision(true, true);

Mesh.SetActorCollision(false, false);

Mesh.SetHasPhysicsAssetInstance(false,false)

 

最终效果:

MyMOBAGame刚体碰撞切换时,为了让角色不容易掉到地面下,取消FootPlacement。为了缓解角色悬空,当角色站在比较斜的位置直接调用刚体,让角色倒下。

(相关代码:WalkableFloorZ,上不去就滑下)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值