项目
所谓的逻辑分析
主要是Spawn函数生成一个类,需要指定生成位置,子弹类在游戏中生成除了生成位置还要能看到它,要看到它就要粒子特效,生成的子弹类要运动,运动就要有方向和速度,
在UDK中生成子弹用的是Socket,生成的位置就是Socket在世界空间中的位置,特效产生的位置也在Socket位置,粒子系统组件就附加到Socket,武器开火有声音,,,,
不明白为什么上面提到的三个东西在UDK中都好像需要在结构体中定义才能生效,好像结构体的名字都是固定好了的,要访问它们又要通过结构体变量访问,
所以生成子弹用到的东西不多,只是代码有点绕。
最终实现效果(发射四个射弹)
在Editor中创建的四个Scoket
代码部分:
ClassMyState_Test extendsPawn
placeable;
// Sounds for turret behaviors
structTurretSoundGroup
{
var()SoundCueFireSound; //开火时播放的声音
};
//PSystems for the turret
structTurretEmitterGroup
{
var()ParticleSystemMuzzleFlashEmitter; //开火时的枪口火焰特效
var()FloatMuzzleFlashDuration; //应该是粒子系统持续时间间隔吧
structdefaultproperties
{
MuzzleFlashDuration=0.33 //结构体成员附初值
}
};
//Bone, Socket, Controller names
structTurretBoneGroup
{
var()NameFireSocket; //开火时的骨骼,插槽;在Editor中插槽的名字
var()Namefs11;
var()Namefs44;
var()Namefshh;
};
varVector FireLocation; //World position of the firing socket,定义骨骼,插槽;三维空间世界坐标系中的位置变量------本例中用来生成枪口火焰和子弹的初始位置
varRotator FireRotation; //World orientation of the firing socket 定义骨骼,插槽的旋转(方向)
varVector FireLocation11; //骨骼,插槽;三维空间世界坐标系中的位置------本例中用来生成枪口火焰和子弹的初始位置
varVector FireLocation44; //定义骨骼,插槽的旋转(方向)变量
varVector FireLocationhh;
varRotator FireRotation11;
varRotator FireRotation44;
varRotator FireRotationhh;
varParticleSystemComponentMuzzleFlashEffect; //PSys component for playing muzzleflashes
varParticleSystemComponentMuzzleFlashEffect1;//粒子系统组件,用来播放枪口火焰特效
varParticleSystemComponentMuzzleFlashEffect2;
varParticleSystemComponentMuzzleFlashEffect3;
/*Designer editable variables
* 定义在Editor(Turret栏)中可编辑的变量
* */
var(Turret)DynamicLightEnvironmentComponent LightEnvironment; //LightEnvironment for the turret
var(Turret)TurretBoneGroup TurretBones; //Bone, Socket,Controller names,访问骨骼结构体的变量
var(Turret)class<Projectile>ProjClass; //Type of projectile the turret fires,定义射弹的类变量
var(Turret)Int RoundsPerSec; //Numberof rounds to fire per second,每秒钟发射多少个子弹
var(Turret)TurretEmitterGroup TurretEmitters; //PSystems used bythe turret访问粒子特效结构体的变量
var(Turret)TurretSoundGroup TurretSounds; //Sounds usedfor different turret behaviors访问声音结构体的变量
//游戏开始前需要初始化的一些资源
eventPostBeginPlay()
{
Super.PostBeginPlay();
Mesh.GetSocketWorldLocationAndRotation(TurretBones.FireSocket,FireLocation,FireRotation,0); //设置枪口火焰插槽的位置和旋转(函数的作用是对前面定义的变量FireLocation,FireRotation附值)-----Mesh =SkeletalMeshComponet
//Mesh.GetSocketWorldLocationAndRotation(TurretBones.FireSocket,FireLocation,FireRotation,0); //第一个变量类型是name,第二个是vector,第三个是rotator,第四个是int,0 == World, 1 == Local (Component)(0表示世界坐标,1表示组件的相对坐标,默认返回的是世界坐标,如果把改成,在本例的测试中看不到子弹)
Mesh.GetSocketWorldLocationAndRotation(TurretBones.fs11,FireLocation11,FireRotation11);
Mesh.GetSocketWorldLocationAndRotation(TurretBones.fs44,FireLocation44,FireRotation44);
Mesh.GetSocketWorldLocationAndRotation(TurretBones.fshh,FireLocationhh,FireRotationhh);
//设置(粒子系统组件)模板
MuzzleFlashEffect.SetTemplate(TurretEmitters.MuzzleFlashEmitter);
MuzzleFlashEffect1.SetTemplate(TurretEmitters.MuzzleFlashEmitter);
MuzzleFlashEffect2.SetTemplate(TurretEmitters.MuzzleFlashEmitter);
MuzzleFlashEffect3.SetTemplate(TurretEmitters.MuzzleFlashEmitter);
//附加粒子系统组件到Socket
Mesh.AttachComponentToSocket(MuzzleFlashEffect,TurretBones.FireSocket);
Mesh.AttachComponentToSocket(MuzzleFlashEffect1,TurretBones.fs11);
Mesh.AttachComponentToSocket(MuzzleFlashEffect2,TurretBones.fs44);
Mesh.AttachComponentToSocket(MuzzleFlashEffect3,TurretBones.fshh);
SetPhysics(PHYS_None);
}
//TakeDamage事件,当这个Actor受到伤害时使它进入一个状态
eventTakeDamage(intDamage, ControllerInstigatedBy,vectorHitLocation,vectorMomentum,class<DamageType>DamageType,optionalTraceHitInfoHitInfo,optionalActorDamageCauser)
{
GotoState('Defend');
}
//声明一个状态
stateDefend
{
functionBeginFire()
{
if(RoundsPerSec > 0)
{
SetTimer(1.0/RoundsPerSec,true,'TimedFire'); //Actor的时间函数,每过.0/RoundsPerSec的时间,运行一次TimedFire函数--True,循环计时器
}
}
//在US中,不带参数的函数都是可以用作时间函数
functionTimedFire()
{
localProjectileProj; //定义子弹类的局部变量(子弹产生又消失,定义局部变量更合适
localProjectileProj11;
localProjectileProj44;
localProjectileProjhh;
//Spawn函数生成的子弹类附值给定义的子弹类变量,子弹在世界中生成的位置就是初使化过的骨骼插槽在世界空间中的位置变量
Proj=Spawn(ProjClass,self,,FireLocation,FireRotation,,True);
Proj11=Spawn(ProjClass,self,,FireLocation11);
Proj44=Spawn(ProjClass,self,,FireLocation44);
Projhh=Spawn(ProjClass,self,,FireLocationhh);
if(Proj !=None&& !Proj.bDeleteMe) //如果产生的子弹存在并且没有被删除(消失)
{
Proj.Init(Vector(FireRotation)); //对子弹进行速度的初使化(把骨骼插槽的(旋转)朝向转化成失量作为它的速度方向)
//这样骨架网格物在三维空间中移动旋转,生成的子弹也会随着骨架网格物移动和旋转。因为骨架网格物在游戏过程中运动时,Soket会保持着和骨架网格物相对不变的移动和旋转
/*子弹产生后,使用同一个方向射出
Proj11.Init(Vector(FireRotation));
Proj44.Init(Vector(FireRotation));
Projhh.Init(Vector(FireRotation));
*/
//子弹产生后,沿各自Socket的定义的方向射出
Proj11.Init(Vector(FireRotation11));
Proj44.Init(Vector(FireRotation44));
Projhh.Init(Vector(FireRotationhh));
}
if(TurretEmitters.MuzzleFlashEmitter!=None) //如果存在枪口火焰发射器(如果定义了粒子系统变量,并对变量附了值)
{
MuzzleFlashEffect.ActivateSystem(); //激活枪口火焰粒子特效
//SetTimer(TurretEmitters.MuzzleFlashDuration,false,'StopMuzzleFlash');
MuzzleFlashEffect1.ActivateSystem();
//SetTimer(TurretEmitters.MuzzleFlashDuration,false,'StopMuzzleFlash');
MuzzleFlashEffect2.ActivateSystem();
//SetTimer(TurretEmitters.MuzzleFlashDuration,false,'StopMuzzleFlash');
MuzzleFlashEffect3.ActivateSystem();
SetTimer(TurretEmitters.MuzzleFlashDuration,false,'StopMuzzleFlash'); //计时器函数,MuzzleFlashDuration变量定义的是粒子特效所谓的持续时间,过了那个时间后就执行StopMuzzleFlash函数关掉特效--false,非循环
}
if(TurretSounds.FireSound!=None) //如果开火的声音存在(如果成功定义了声音)
PlaySound(TurretSounds.FireSound); //播放音效----If后面如果没有添加{},跟在if后面的第一名代码就是判断后是否要执行的语名,其它的都不属于If语句的内容了。
}
functionStopMuzzleFlash()
{
MuzzleFlashEffect.DeactivateSystem(); //粒子特效设为非激活状态
MuzzleFlashEffect1.DeactivateSystem();
MuzzleFlashEffect2.DeactivateSystem();
MuzzleFlashEffect3.DeactivateSystem();
}
eventBeginState(NamePreviousStateName) //作为Defend状态,当进入这人状态函数时首先要执行的代码BeginState,不明白可参考US状态编程
{
SetTimer(1.0,false,'BeginFire');
}
eventEndState(NameNewStateName)
{
ClearTimer('TimedFire');
}
}
defaultproperties
{
//为了让骨架网格物体可见,定义动态光照组件
BeginObjectClass=DynamicLightEnvironmentComponent Name=MyLightEnvironment
EndObject
LightEnvironment=MyLightEnvironment
Components.Add(MyLightEnvironment) //定义了组件,要使组件可用和生效,需要Add到Component
//定义SkeletalMesh
BeginObjectclass=SkeletalMeshComponent name=SkelMeshComp0
SkeletalMesh=SkeletalMesh'MyState_Chapter11pck.FBX_Gun_Mesh'
AnimTreeTemplate=AnimTree'MyState_Chapter11pck.FBX_Gun_Mesh_AnimTree'
PhysicsAsset=PhysicsAsset'MyState_Chapter11pck.FBX_Gun_Mesh_Physics'
//Scale3D=(X=2.0,Y=2.0,Z=5.0)
LightEnvironment=MyLightEnvironment //动态光照
EndObject
Components.Add(SkelMeshComp0)
/*粒子系统组件,本例中想实现四个射弹,所以定义了四个粒子组件分别把它们添加到Component的-3号数组中*/
BeginObjectClass=ParticleSystemComponent Name=ParticleSystemComponent0
SecondsBeforeInactive=1
EndObject
Components.Add(ParticleSystemComponent0)
MuzzleFlashEffect=ParticleSystemComponent0
BeginObjectClass=ParticleSystemComponent Name=ParticleSystemComponent1
SecondsBeforeInactive=1
EndObject
Components.Add(ParticleSystemComponent1)
MuzzleFlashEffect1=ParticleSystemComponent1
BeginObjectClass=ParticleSystemComponent Name=ParticleSystemComponent2
SecondsBeforeInactive=1
EndObject
Components.Add(ParticleSystemComponent2)
MuzzleFlashEffect2=ParticleSystemComponent2
BeginObjectClass=ParticleSystemComponent Name=ParticleSystemComponent3
SecondsBeforeInactive=1
EndObject
Components.Add(ParticleSystemComponent3)
MuzzleFlashEffect3=ParticleSystemComponent3
//把Editor中Soket的名字附值给定义的骨骼插槽结构体中的成员
TurretBones={(
FireSocket=FireLocation,
fs11 =f11,
fs44 =f44,
fshh =fhh,
)}
TurretSounds={(
FireSound=SoundCue'A_Weapon_Link.Cue.A_Weapon_Link_FireCue',
)}
//枪口火焰特效用到的粒子系统
TurretEmitters={(
MuzzleFlashEmitter=ParticleSystem'WP_Stinger.Particles.P_Stinger_3P_MF_Alt_Fire',
)}
//生成射弹用到的类(这里用的是LinkPowerPlasma,UDK自带的林肯枪
ProjClass=class'UTGame.UTProj_LinkPowerPlasma'
RoundsPerSec= 3
bEdShouldSnap=true
}