I think, everyone played at least one RTS game. And most RTS games include building. Important part of this system is choosing place for new structure. Usually it is implemented as circle or square, representing physical size of building, which also allows to see, if it is possible to build at this place. And i need thing like this in my game, but i don't know how to implement it properly. I've tryed to attach actor with square static mesh to cursor, and when it collides with something, it becomes red, which means, there is no way you can build here. But i have two problems: this actor makes no collision with anything (at least, if using Touch event), and due to some properties of my mouse cursor interface, when i hover my cursor over strucrures, this square is displayed on top of this structures. So, is there any proper code for this thing?
Announcement
Collapse
No announcement yet.
Best way for building area selection
Collapse
X
-
Hi there!
My PS near bottom has the code for you, hopefully first part will help others.
you can easily make it so that while you are using your static mesh as a moveable cursor icon it will also collide with world geometry
I recommend using MoveSmooth to ensure that as you drag the cursor your mesh will attempt to rise above any interfering geometry
please note that MoveSmooth, and your general goal, requires bCollideWorld = true
here's a custom static mesh class that could be your building footprint:
Spawn a instance of this class in game whenever entering building mode using spawn
See note at bottom about using Trace to know where to position the footprint at spawn time
Code:class BuildingFootPrint extends StaticMeshActor placeable; defaultproperties{ Begin Object class=DynamicLightEnvironmentComponent Name=joyLightEnv bEnabled = true bCastShadows = true //false End Object Components.Add(joyLightEnv) Begin Object Name=StaticMeshComponent0 LightEnvironment=joyLightEnv CastShadow=false BlockRigidBody=true BlockZeroExtent=true bUsePrecomputedShadows=false StaticMesh=StaticMesh'VictoryPackage.Meshes.gem' //replace with your mesh RBCollideWithChannels=(Default=true) bAllowAmbientOcclusion=false End Object CollisionComponent=StaticMeshComponent0 bStatic=false bMovable=true bCollideActors = true bNoDelete = false //prevents mesh from moving thru world geometry //use a trace to find ground beneath this obj //to know what z-height to move it to so it is //always visible bCollideWorld = true }
Highlight On Collision
you can use RBCollision event to tell when your static mesh collides with something and have it change color and also identify what the static mesh collided with
EverNewJoy RB Collision Event Tutorial
Rama
PS: re-reading your post, if you DONT want your static mesh to rise above structures, you will need to use a different setup
here's a class that HAS collision (so it does detect RBCollision events), but this mesh will NOT rise above other structures and will go right through them if you use SetLocation or Move
Code:class BuilderFootPrint extends StaticMeshActor placeable; 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 StaticMesh=StaticMesh'JoyfulPackage.Meshes.basicCube256' RBCollideWithChannels=(Default=true) bAllowAmbientOcclusion=false End Object CollisionComponent=StaticMeshComponent0 bStatic=false bMovable=true bCollideActors = true }
the important lines here:
bNotifyRigidBodyCollision = true
ScriptRigidBodyCollisionThreshold = 1
bCollideActors = true
this gets you the RBCollision Event as long as your structures also have similar settings.
EverNewJoy RB Collision Event Tutorial
then you can use othercomponent.Owner to get the actor that was collided with
but if you use SetLocation or Move (move is way better by the way, more efficient), you can slide your static mesh right through other objects.
Rama
PS: I do this all the time in my game, see this video showing a mesh that has collision but can be forced through world geometry, but will STILL support a Kactor:
about 3:40 into video
-
evernewjoy, thx for your reply, i've made some fixes to my static mesh component, and now it gets Touch function well, but second problem is not still solved. Since i'm using DeProject to make 2d mouse cursor coordinates to 3d world coordinates, and i use this 3d world coords to place my selection actor, once my cursor is over existing building, selection actor is not intersecting with this building, it's just on top of this building. Look at screnshots.
It looks nice here, because cursor is over floor. And here
Cursor is over building, and selection actor is messed up.
Comment
-
Assuming you're using a simple Trace and its HitLocation to find the 3d coordinate this should be the expected result (depending on properties). Trace hits the Actor that's already been placed, therefore the second Actor is placed on top of it because that's the HitLocation. If you want to make sure your Actors will be placed on the ground, you'll first need to know what your ground is made up off: Terrain, Landscape, Worldinfo, StaticMeshes, etc.? If the simple Trace returns a type that doesn't match one of those you want you'll need to trace again (or use TraceActors to only Trace against certain Actortypes) until the Trace hits the 'floor'.
If you don't know the Actorclasses or don't want to do it that way you can also use TraceActors and Trace everything, it will give you every hit result along a line. If something that was hit has some class that you don't want to place stuff on top ignore it and look at the next result of the iterator.
Comment
-
UnrealEverything brings up some great points
sooo
why not just make the actor that is obviously in the way glow red? (the actor that is below the cursor)
that should look good visually and make it obvious who your game engine thinks is obstructing the building area.
you can use
Code://global var Actor buildingThatIsInTheWay; var string originalmaterial; function f(){ buildingThatIsInTheWay = trace(....); if(buildingThatIsInTheWay != none){ originalmaterial = PathName(buildingThatIsInTheWay.StaticMeshComponent.GetMaterial(0)); buildingThatIsInTheWay.StaticMeshComponent.SetMaterial(0, Material'GDC_Materials.Materials.M_RibbonBlade_1'); } } then when cursor is not over the building anymore buildingThatIsInTheWay.StaticMeshComponent.SetMaterial(0, Material(DynamicLoadObject(originalmaterial, class'Material')));
Rama
PS: your UDK has the red material I'm using in this code
Comment
Comment