Announcement

Collapse
No announcement yet.

Best way for building area selection

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Best way for building area selection

    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?

    #2
    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

    Comment


      #3
      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


        #4
        Well, it can be solved, if i will not change material, but just hide this actor when it's not possible to build here (including situation with cursor over building). But, it will look worse than with changing mat.

        Comment


          #5
          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


            #6
            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

            Working...
            X