Dear Community,
I've finally done it!
I've created a hybrid object that is both a Kactor and an Apex Destructible Mesh!
So now you can push around a kactor in all ways a normal kactor behaves, and then shoot it to destroy it in tiny pieces!
Launch a kactor high into the air! Watch it spin! Then make it explode in mid air!
I made a video of me doing this using my game engine!
This video footage is entirely one continous shot and un-edited, all the saving/loading and changing of maps is done real-time in my game engine.
I spent many months to create this in-game 3D editor with saving/loading features, and this is only one small part of my game engine
Enjoy watching exploding Apex Destructible Kactors!
Below the video is all the core code you need to be able to implement Destructible Kactors
~~~
All the Core Code You Need To Do This
With the code below I am providing you with several options, all from a static mesh actor placeholder that you put in the level where you want to spawn a kactor, or an apex that does not move.
So there's two major cases
1. static mesh actor becomes apex directly
2. static mesh actor becomes kactor, which then blows up as an apex
see spawnApex()
and becomeKActor()
for respective cases, in the static mesh actor place holder class.
Why have a place holder static mesh actor?
Well both the kactor and the apex get destroyed, because they take up more system resources than a simple static mesh.
So to restart the simulation, you can just keep reactivating the static mesh place holder wherever you position it in your level.
Static mesh actor is never destroyed, just made invisible and no collision
~~~
The Base Custom Apex Destructible Class
With Set Inner and Outer Materials
A specific instance of base Apex Class
That utilizes a specific Apex Asset You Make
~~~
The Static Mesh Actor Place Holder
This is the placeholder static mesh actor
It is made invisible at game/simulation start if you are using the Kactor option, otherwise it stays visible as a static solid mesh until a projectile collides with it, at which point it turns into apex and gets destroyed/
See the GameMode() section.
That is the code you can translate to your project as “start simulation” or “restart simulation”
so you can blow up the apex multiple times without leaving your game completely.
~~~
The Kactor Class Spawned by Static Mesh Class
This is the in-game Kactor that moves around in all Kactor-y ways until player shoots it with custom projectile.
~~~
Custom Projectile to Blow Up the Kactor
You must modify your custom projectile class so that it
1. calls the kactor function to blow up the kactor
2. has an affect on Apex Destructibles
~~~
Essential Projectile Class Code
~~~
Setting Custom Projectile to affect Apex Meshes
Review my tutorial for some basic apex destructible info
Here's the essential info from this tutorial:
http://forums.epicgames.com/threads/...g-UnrealScript
Using Custom Projectiles to Shoot Apex Mesh
You have to tell the Apex engine to recognize your custom class projectiles as able to do damage and impart momentum to ALL apex destructibles, this is not specific to any 1 apex destructible
1. Go into UDK
2. click All Assets
3. do a filter for apex
4. Find the Apex Destructible Damage Parameters
5. Double click on it and add a new element (green + sign)
6. set the Name to be the name of your class, just the name itself
7. set the values, make sure the momentum is something like 2000 or so
8. Set base damage to something like 100 and radius to something like 50
9. SAVE THE APEX PACKAGE by right clicking on the thing you just edited and click save
~~~
Destructible Apex Kactors!
This is all the core code you need to do what I did in the video!
All the saving/loading and loading of different maps pertains more to my level editor and I stripped all that code so you can see the essential basics of the classes.
Have fun implementing this fun Kactor-Apex techology!
♥
Rama
I've finally done it!
I've created a hybrid object that is both a Kactor and an Apex Destructible Mesh!
So now you can push around a kactor in all ways a normal kactor behaves, and then shoot it to destroy it in tiny pieces!
Launch a kactor high into the air! Watch it spin! Then make it explode in mid air!
I made a video of me doing this using my game engine!
This video footage is entirely one continous shot and un-edited, all the saving/loading and changing of maps is done real-time in my game engine.
I spent many months to create this in-game 3D editor with saving/loading features, and this is only one small part of my game engine

Enjoy watching exploding Apex Destructible Kactors!
Below the video is all the core code you need to be able to implement Destructible Kactors
~~~
All the Core Code You Need To Do This
With the code below I am providing you with several options, all from a static mesh actor placeholder that you put in the level where you want to spawn a kactor, or an apex that does not move.
So there's two major cases
1. static mesh actor becomes apex directly
2. static mesh actor becomes kactor, which then blows up as an apex
see spawnApex()
and becomeKActor()
for respective cases, in the static mesh actor place holder class.
Why have a place holder static mesh actor?
Well both the kactor and the apex get destroyed, because they take up more system resources than a simple static mesh.
So to restart the simulation, you can just keep reactivating the static mesh place holder wherever you position it in your level.
Static mesh actor is never destroyed, just made invisible and no collision
~~~
The Base Custom Apex Destructible Class
With Set Inner and Outer Materials
Code:
class JoyfulDestruction extends ApexDestructibleActorSpawnable placeable; function joyfulSetMaterial(Material outside, Material inside) { if (outside == None || inside == None) { `log("joyfulSetMaterial: sent invalid materials"); return; } //note the index of 1 for the inner material //that is visible when apex is destroyed StaticDestructibleComponent.SetMaterial(0, outside); StaticDestructibleComponent.SetMaterial(1, inside); } defaultproperties { Begin Object name=DestructibleComponent0 bAllowAmbientOcclusion=false //change to your asset, look up entire path of your APEX by going into UDK //right click on your APEX and get the full name, copy into your code Asset = ApexDestructibleAsset'JoyfulPackage.Destruction.CubeCutOut256' //sets collison/colliding on fracture pieces of Apex mesh //I looked this up in Engine/ActorFactoryApexDestructible.uc //and added "RB" to front of "CollideWithChannels" RBChannel=RBCC_EffectPhysics RBCollideWithChannels={( Default=TRUE, BlockingVolume=TRUE, GameplayPhysics=TRUE, EffectPhysics=TRUE )} End Object }
That utilizes a specific Apex Asset You Make
Code:
class VictoryDestructionCube extends JoyfulDestruction
placeable;
defaultproperties
{
Begin Object class=DynamicLightEnvironmentComponent Name=joyLightEnv
bEnabled = true
bCastShadows = true //false
End Object
Components.Add(joyLightEnv)
Begin Object name=DestructibleComponent0
LightEnvironment=joyLightEnv
//replace this with the package name of your own
//destructible asset
//to make destructible assets go to nvidia website
//and download apex labs
//http://supportcenteronline.com/ics/support/default.asp?deptID=1949
Asset = ApexDestructibleAsset'VictoryPackage3.apex.cube256TotalDestroy';
End Object
}
The Static Mesh Actor Place Holder
This is the placeholder static mesh actor
It is made invisible at game/simulation start if you are using the Kactor option, otherwise it stays visible as a static solid mesh until a projectile collides with it, at which point it turns into apex and gets destroyed/
See the GameMode() section.
That is the code you can translate to your project as “start simulation” or “restart simulation”
so you can blow up the apex multiple times without leaving your game completely.
Code:
class VictoryDWall extends StaticMeshActor placeable; //custom player controller class var CustomController custController; //this is a simplified version //of my save/load struct //You can use basicsaveobject //to save states of each of your objs //to computer hard disk //only using structs //dynamic objects cannot be saved //by basicsave object //so all pertinent data must be stored //as a struct //for this tutorial though //this is irrelevant //but that's why this info is in a struct struct DWallstruct { var string meshType; var string materialType; var string interiorMaterialType; var vector startlocation; var rotator startrotation; //KActor var bool isKactor; var bool kActorStartsAwake; var bool destroyed; structdefaultproperties { isKactor = true //default inner material for apex interiorMaterialType = "JoyfulPackage.DestructionMaterials.Blackrock02_destructionmat" kActorStartsAwake = true } }; var DWallstruct info; //not-saved Kactor child link var JoyKactor childJoyKactor; function SetDisabled(bool b) { //disabled info.disabled = b; //KACTOR if(info.isKactor) { //check has child kactor if (childJoyKactor == none) return; //hidden childJoyKactor.setHidden(b); //collision if(b) childJoyKactor.SetCollisionType(COLLIDE_BlockAll); else childJoyKactor.SetCollisionType(COLLIDE_NoCollision); } //NON KACTOR else { setHidden(b); if(b) SetCollisionType(COLLIDE_BlockAll); else SetCollisionType(COLLIDE_NoCollision); } } function setStart() { info.startlocation = Location; info.startRotation = Rotation; } function spawnApex() { local JoyfulDestruction d; //hide parent info.destroyed = true; SetHidden(true); SetCollisionType(COLLIDE_NoCollision); if(info.meshtype == "JoyfulPackage.Meshes.basicCube256"){ d = Spawn(class'VictoryDestructionCube',,, Location,Rotation); //set to material of this instance d.joyfulSetMaterial(Material( DynamicLoadObject(PathName(StaticMeshComponent.GetMaterial(0)), class'Material')), Material(DynamicLoadObject(info.interiorMaterialType, class'Material')) ); } //store dynamic generated object in dynamic array //custController.levelDestruction.addItem(d); } function becomeKActor() { if (!info.isKactor) return; //hide parent SetHidden(true); SetCollisionType(COLLIDE_NoCollision); //create kactor //set child childJoyKactor = Spawn(class'JoyKactor',,, Location, Rotation); //set parent childJoyKactor.parentDwall = Self; //** * * *** set to dwallkactor *** * * ** childJoyKactor.isDwallKactor = true; //init including MASS childJoyKactor.joyInit(custController, info.meshType, info.materialtype, 100); //WHETHER TO WAKE AT GAME START OR NOT if (info.kActorStartsAwake) childJoyKactor.wake(); } //hit by projectile function DwallHit(vector hitNormal) { spawnApex(); } //GAME MODE //you can use the core of this code //to see how to activate/initiate //your usage of this class. //For my game I toggle game mode //each time player loads/reloads map //while in the game editor function toggleGameMode(bool b) { //GAME MODE if (b) { //KACTOR if (info.isKactor) { becomeKActor(); } //Non-KACTOR else { //if it was hidden if(bhidden){ SetHidden(false); SetCollisionType(COLLIDE_BlockAll); } info.destroyed = false; } //TEST CODE ONLY //disable above code //that turns it into Kactor //to just make an apex first //spawnApex(); } //EDITOR MODE else { //show disabled walls again if(bhidden){ self.SetHidden(false); self.SetCollisionType(COLLIDE_BlockAll); } } } //JoyInit //takes in strings that are the path //for the regular static mesh to use //and the material to use. //use PathName() to get the string for your //mesh and material assets //for example //PathName(StaticMeshActor(a).StaticMeshComponent.GetMaterial(0)); function joyInit(CustomControllerer custControllerin, string curMeshType, string curMaterialType ) { custController = custControllerin; //collision self.SetCollision(true,true); self.SetCollisionType(COLLIDE_BlockAll); self.CollisionComponent.SetRBCollidesWithChannel(RBCC_Default,true); //scale //cant scale apex so use normal scaling self.StaticMeshComponent.SetScale3D(vect(1,1,1)); //Set Mesh From String StaticMeshComponent.SetStaticMesh( StaticMesh(DynamicLoadObject(curMeshType, class'StaticMesh'))); //Set Material from String StaticMeshComponent.SetMaterial(0, Material( DynamicLoadObject(curMaterialType, class'Material'))); //info info.meshtype = curMeshType; info.materialType = curMaterialType; //Distance Culling staticmeshcomponent.SetCullDistance(40000); } DefaultProperties { //if having performance issues try removing this Begin Object class=DynamicLightEnvironmentComponent Name=joyLightEnv bEnabled = true bCastShadows = false //false End Object Components.Add(joyLightEnv) Begin Object Name=StaticMeshComponent0 LightEnvironment=joyLightEnv CastShadow = false //false bUsePrecomputedShadows=false BlockRigidBody=true BlockZeroExtent=true //RB Collision bNotifyRigidBodyCollision = true ScriptRigidBodyCollisionThreshold = 1 //a default starting mesh StaticMesh=StaticMesh'JoyfulPackage.Meshes.basicCube256' RBCollideWithChannels=(Default=true) bAllowAmbientOcclusion=false End Object //important settings to enable mesh //to be spawned using spawn(class'VictoryDwall') bStatic=false bMovable=true CollisionComponent=StaticMeshComponent0 bCollideActors = true }
The Kactor Class Spawned by Static Mesh Class
This is the in-game Kactor that moves around in all Kactor-y ways until player shoots it with custom projectile.
Code:
Class JoyKactor Extends KActorSpawnable Placeable; var bool isDwallKactor; var customController custController; var VictoryDWall parentDwall; //makes it so kactor will fall //if it is positioned to start in the air //at start of simulation/gametime function wake() { StaticMeshComponent.WakeRigidBody(); } //very useful to fine tune //interaction of kactor with apex //destructible chunks function setMass(float newMass) { local RB_BodySetup rbs; //invalid values if (newMass <= 0) return; rbs = new Class'RB_BodySetup'; rbs.MassScale = newMass; ( Self.StaticMeshComponent.GetRootBodyInstance() ).UpdateMassProperties(rbs); } function spawnApex() { local JoyfulDestruction d; if (parentDwall == none){ `log(Self.name@"spawned kactor lost its parent"); return; } //destroy kactor destroy(); //set parent destroyed value parentDwall.info.destroyed = true; //can add other shapes using similar code //this is the mesh the previous class was using //as its default if(parentDwall.info.meshtype == "JoyfulPackage.Meshes.basicCube256"){ //the specific destruction class explained earlier //in this tutorial d = Spawn(class'VictoryDestructionCube',,, Location,Rotation); //set inner and outer materials, see JoyfulDestruction //base class d.joyfulSetMaterial( Material(DynamicLoadObject(parentDwall.info.materialtype, class'Material')), Material(DynamicLoadObject(parentDwall.info.interiorMaterialType, class'Material')) ); } } //hit by projectile function DwallKactorHit() { spawnApex(); } //see the note in the StaticMeshActor class //about how the init parameters work //addition is ability to set initial mass //very useful function joyInit(customController custControllerin, string meshType, string materialType, float mass) { custController = custControllerin; //add to array //custController.levelJoyKactors.additem(Self); //mass setMass(mass); //Set Mesh From String StaticMeshComponent.SetStaticMesh(StaticMesh( DynamicLoadObject(meshType, class'StaticMesh'))); //Set Material from String StaticMeshComponent.SetMaterial(0, Material(DynamicLoadObject(materialType, class'Material'))); } defaultproperties { bCollideActors = true //bWakeOnLevelStart = true }
Custom Projectile to Blow Up the Kactor
You must modify your custom projectile class so that it
1. calls the kactor function to blow up the kactor
2. has an affect on Apex Destructibles
~~~
Essential Projectile Class Code
Code:
//this projectile class extended //UTGame/UTProjectile.uc //essential functions //in case you want your projectiles to bounce function bounce(vector HitNormal) { Velocity = MirrorVectorByNormal (Velocity, HitNormal); Acceleration = AccelRate * Normal(Velocity); SetRotation(Rotator(Velocity)); } //hitwall for kactors, dynamicStaticMesh Actors //NOT for apex //for apex projectile interaction see last section //you don't need to call super //I copied all essential code simulated event HitWall(vector HitNormal, Actor Wall, PrimitiveComponent WallComp) { //projectile code local KActorFromStatic NewKActor; local StaticMeshComponent HitStaticMesh; //pseudo code for case of projectile //hitting your pawn /* if (Wall == playerpawn) { //do nothing but bounce off } */ //DWall if (Wall.isa('VictoryDwall')){ //case 1: static mesh placeholder to //apex directly VictoryDwall(Wall).DwallHit(HitNormal); Destroy(); return; } //JoyKactor else if (Wall.isa('joyKactor')){ //case 2: kactor to apex //Dwall Kactor ? if (joyKactor(Wall).isDwallKactor) { //dwallKactor joyKactor(Wall).DwallKactorHit(); //make projectile stay so it hits the apex //no bouncing no other code //so projectle pushes against kactor //and kactor turns into apex //and projectle explodes on apex //see last section of tutorial for //how to make apex asset react //to projectile return; } //apply impulse if kactor not set to become apex else { joyKactor(Wall).StaticMeshComponent.AddImpulse( HitNormal * 10000, Location); Destroy(); } } //all other walls else { //Victory Code MomentumTransfer = 1.0; //actor code TriggerEventClass(class'SeqEvent_HitWall', Wall); if ( Wall.bWorldGeometry ) { HitStaticMesh = StaticMeshComponent(WallComp); if ( (HitStaticMesh != None) && HitStaticMesh.CanBecomeDynamic() ) { NewKActor = class'KActorFromStatic'.Static.MakeDynamic(HitStaticMesh); if ( NewKActor != None ) { Wall = NewKActor; } } } ImpactedActor = Wall; if ( !Wall.bStatic && (DamageRadius == 0) ) { Wall.TakeDamage( Damage, InstigatorController, Location, MomentumTransfer * Normal(Velocity), MyDamageType,, self ); } //Explode(Location, HitNormal); ImpactedActor = None; //Victory Bounce code bounce(HitNormal); } //END of all other walls case }
~~~
Setting Custom Projectile to affect Apex Meshes
Review my tutorial for some basic apex destructible info
Here's the essential info from this tutorial:
http://forums.epicgames.com/threads/...g-UnrealScript
Using Custom Projectiles to Shoot Apex Mesh
You have to tell the Apex engine to recognize your custom class projectiles as able to do damage and impart momentum to ALL apex destructibles, this is not specific to any 1 apex destructible
1. Go into UDK
2. click All Assets
3. do a filter for apex
4. Find the Apex Destructible Damage Parameters
5. Double click on it and add a new element (green + sign)
6. set the Name to be the name of your class, just the name itself
7. set the values, make sure the momentum is something like 2000 or so
8. Set base damage to something like 100 and radius to something like 50
9. SAVE THE APEX PACKAGE by right clicking on the thing you just edited and click save
~~~
Destructible Apex Kactors!
This is all the core code you need to do what I did in the video!
All the saving/loading and loading of different maps pertains more to my level editor and I stripped all that code so you can see the essential basics of the classes.
Have fun implementing this fun Kactor-Apex techology!
♥
Rama
Comment