Ruud033 Posted June 16, 2015 Share Posted June 16, 2015 (edited) Code is bugging, dont know why //============================================================================= // FoliageCollisionVolume: a vehicle collision solution // used to collide certain classes of actors // primary use is to provide collision for non-zero extent traces around static meshes // Created by Pinheiro, https://forums.epicgames.com/threads/913559-How-to-enable-collision-on-foliage //============================================================================= class FoliageCollisionVolume extends Volume placeable; static final function vector MatrixGetScale(Matrix TM) { local Vector s; s.x = sqrt(TM.XPlane.X**2 + TM.XPlane.Y**2 + TM.XPlane.Z**2); s.y = sqrt(TM.YPlane.X**2 + TM.YPlane.Y**2 + TM.YPlane.Z**2); s.z = sqrt(TM.ZPlane.X**2 + TM.ZPlane.Y**2 + TM.ZPlane.Z**2); return s; } simulated function UpdateCollisionBasedOnDistanceTimer() //simulated functions are MAYBE client side only, have to try this! { local float CollisionDistance; local playercontroller PC; if(PC.Pawn == None) return; CollisionDistance = VSize(PC.Pawn.location - location); //The distance between the two actors if(CollisionDistance<=400) //Checks when ever to create collision or what ever number if you have that { SetTimer(0.6f,false,'CreateCollision'); CollisionDistance =400; } function CreateCollision() { local InstancedFoliageActor ac; local InstancedStaticMeshComponent comp; local vector loc, scale; local Rotator rot; local BlockingMesh CreatedBlockingMesh; local int i, j; super.CreateCollision(); //look for the InstancedFoliageActor foreach AllActors(class'InstancedFoliageActor',ac) { //iterate through the various foliage components for(i=0; i { comp = ac.InstancedStaticMeshComponents[i]; if (comp.StaticMesh.BodySetup != none) { //iterate through the various meshes in this component, if it has a collision model for (j=0; j { //decompose the instance's transform matrix loc = MatrixGetOrigin(comp.PerInstanceSMData[j].Transform); if (ContainsPoint(loc)) //check if this instance is within the volume { rot = MatrixGetRotator(comp.PerInstanceSMData[j].Transform); scale = MatrixGetScale(comp.PerInstanceSMData[j].Transform); CreatedBlockingMesh = Spawn(class'BlockingMesh',ac,,loc,rot); CreatedBlockingMesh.StaticMeshComponent.SetStaticMesh(comp.StaticMesh); CreatedBlockingMesh.SetDrawScale3D(scale); } } } } } } } ---------------------F:\Program Files\Renegade X Beta4\SDK\Development\Src\FoliageCollisionVolume\Classes\FoliageCollisionVolume.uc(36) : Error, 'Function' is not allowed here Failure - 1 error(s), 0 warning(s) Execution of commandlet took: 4.37 seconds [jun 16, 10:46 ] COMMANDLET 'UDK.exe make' FAILED Edited June 23, 2015 by Guest Quote Link to comment Share on other sites More sharing options...
Crnyo Posted June 16, 2015 Share Posted June 16, 2015 function UpdateCollisionBasedOnDistanceTimer() is missing '}' sign. That is causing the error. Quote Link to comment Share on other sites More sharing options...
Ruud033 Posted June 17, 2015 Author Share Posted June 17, 2015 Nope, sorry but it's there already. Is a function within a function allowed?? I've also read somewhere that timers are not supposed to fire a function or something?? (Silo uses the same though) Quote Link to comment Share on other sites More sharing options...
RoundShades Posted June 17, 2015 Share Posted June 17, 2015 Nope, sorry but it's there already. Is a function within a function allowed?? I've also read somewhere that timers are not supposed to fire a function or something?? (Silo uses the same though) If function in function can't work, then make the second function outside the bracket. As long as the timer calls it by name, it should work... if(CollisionDistance<=400) //Checks when ever to create collision or what ever number if you have that { SetTimer(0.6f,false,'CreateCollision'); CollisionDistance =400; } } //<--Add a bracket here... { //<---and also below. That pretty much sums up making them separate. function CreateCollision() { local InstancedFoliageActor ac; local InstancedStaticMeshComponent comp; local vector loc, scale; local Rotator rot; local BlockingMesh CreatedBlockingMesh; local int i, j; Quote Link to comment Share on other sites More sharing options...
Totem Arts Staff Handepsilon Posted June 17, 2015 Totem Arts Staff Share Posted June 17, 2015 Supposedly a function can be fired with Timer ever since Unreal Engine 3 came (can't do so in the previous iteration) So a function within a function isn't necessary.... not that it will work anyways Also Bro, that's kinda confusing. You can't make a function inside a bracket... unless it was a bracket for State, which should not be necessary Quote Link to comment Share on other sites More sharing options...
Ruud033 Posted June 17, 2015 Author Share Posted June 17, 2015 Nope, sorry but it's there already. Is a function within a function allowed?? I've also read somewhere that timers are not supposed to fire a function or something?? (Silo uses the same though) If function in function can't work, then make the second function outside the bracket. As long as the timer calls it by name, it should work... if(CollisionDistance<=400) //Checks when ever to create collision or what ever number if you have that { SetTimer(0.6f,false,'CreateCollision'); CollisionDistance =400; } } //<--Add a bracket here... { //<---and also below. That pretty much sums up making them separate. function CreateCollision() { local InstancedFoliageActor ac; local InstancedStaticMeshComponent comp; local vector loc, scale; local Rotator rot; local BlockingMesh CreatedBlockingMesh; local int i, j; This worked! Below is the code. I still have my doubts about this code, I think it still spawns EVERYTHING once the client is in range of it.. I need to change the code to look for foliage instances, any idea on how to do that? //============================================================================= // FoliageCollisionVolume: a vehicle collision solution // used to collide certain classes of actors // primary use is to provide collision for non-zero extent traces around static meshes // Created by Pinheiro, https://forums.epicgames.com/threads/913559-How-to-enable-collision-on-foliage //============================================================================= class FoliageCollisionVolume extends Volume placeable; static final function vector MatrixGetScale(Matrix TM) { local Vector s; s.x = sqrt(TM.XPlane.X**2 + TM.XPlane.Y**2 + TM.XPlane.Z**2); s.y = sqrt(TM.YPlane.X**2 + TM.YPlane.Y**2 + TM.YPlane.Z**2); s.z = sqrt(TM.ZPlane.X**2 + TM.ZPlane.Y**2 + TM.ZPlane.Z**2); return s; } simulated function UpdateCollisionBasedOnDistanceTimer() //simulated functions are MAYBE client side only, have to try this! { local float CollisionDistance; local playercontroller PC; if(PC.Pawn == None) return; CollisionDistance = VSize(PC.Pawn.location - location); //The distance between the two actors if(CollisionDistance<=400) //Checks when ever to create collision or what ever number if you have that { CollisionDistance =400; SetTimer(0.6f,false,'CreateCollision'); } } simulated function CreateCollision() { local InstancedFoliageActor ac; local InstancedStaticMeshComponent comp; local vector loc, scale; local Rotator rot; local BlockingMesh CreatedBlockingMesh; local int i, j; //look for the InstancedFoliageActor foreach AllActors(class'InstancedFoliageActor',ac) { //iterate through the various foliage components for(i=0; i { comp = ac.InstancedStaticMeshComponents[i]; if (comp.StaticMesh.BodySetup != none) { //iterate through the various meshes in this component, if it has a collision model for (j=0; j { //decompose the instance's transform matrix loc = MatrixGetOrigin(comp.PerInstanceSMData[j].Transform); if (ContainsPoint(loc)) //check if this instance is within the volume { rot = MatrixGetRotator(comp.PerInstanceSMData[j].Transform); scale = MatrixGetScale(comp.PerInstanceSMData[j].Transform); CreatedBlockingMesh = Spawn(class'BlockingMesh',ac,,loc,rot); CreatedBlockingMesh.StaticMeshComponent.SetStaticMesh(comp.StaticMesh); CreatedBlockingMesh.SetDrawScale3D(scale); } } } } } } Quote Link to comment Share on other sites More sharing options...
RoundShades Posted June 17, 2015 Share Posted June 17, 2015 That is a shame, idk why it does that. Since we borrowed SBH code, that would be like being able to see all SBH on the map if a single SBH was in range of you. Anyone else have any clue? Quote Link to comment Share on other sites More sharing options...
Ruud033 Posted June 17, 2015 Author Share Posted June 17, 2015 That is a shame, idk why it does that. Since we borrowed SBH code, that would be like being able to see all SBH on the map if a single SBH was in range of you.Anyone else have any clue? After some hours of thinking and trial and error I've got this code, it compiles well but I think it can't find the correct distance between actor and foliage. I think this is due to PC.Pawn.location, this node is not saying anything to me, its meaningless as far as I know. I had to make a local variable called "PC" (check the code) to get it to work and I still don't know what it does. ###So what I did now is I made a radical change. Now I am determining the locations of the foliage first, THEN check if the player is in range (because I already have the exact location's) THEN check whether the foliage is in a volume or not and THEN spawn the collision. It compiles correctly but still, does not work, it does not spawn in the collision. I think this is due to the playerlocation / actor location. I am thinking about putting a check around the foliage, a trigger zone.. so for instance, if an Rx_Actor is closer than 400 units, the script checks whether it's in a volume and THEN spawns the stuff.. rather than monitoring each player realtime. I don't know how to do that (yet). Have to analyse the trigger volume scripting. This is my code for now (as described in ###) //============================================================================= // FoliageCollisionVolume: a vehicle collision solution // used to collide certain classes of actors // primary use is to provide collision for non-zero extent traces around static meshes // Created by Pinheiro, https://forums.epicgames.com/threads/913559-How-to-enable-collision-on-foliage // Edited by Ruud033 //============================================================================= class FoliageCollisionVolume extends Volume placeable; static final function vector MatrixGetScale(Matrix TM) { local Vector s; s.x = sqrt(TM.XPlane.X**2 + TM.XPlane.Y**2 + TM.XPlane.Z**2); s.y = sqrt(TM.YPlane.X**2 + TM.YPlane.Y**2 + TM.YPlane.Z**2); s.z = sqrt(TM.ZPlane.X**2 + TM.ZPlane.Y**2 + TM.ZPlane.Z**2); return s; } simulated function CreateCollision() { local InstancedFoliageActor ac; local InstancedStaticMeshComponent comp; local vector loc, scale; local Rotator rot; local BlockingMesh CreatedBlockingMesh; local int i, j; local float CollisionDistance; local playercontroller PC; //look for the InstancedFoliageActor foreach AllActors(class'InstancedFoliageActor',ac) { //iterate through the various foliage components for(i=0; i { comp = ac.InstancedStaticMeshComponents[i]; if (comp.StaticMesh.BodySetup != none) { //iterate through the various meshes in this component, if it has a collision model for (j=0; j { //decompose the instance's transform matrix loc = MatrixGetOrigin(comp.PerInstanceSMData[j].Transform); CollisionDistance = VSize(PC.Pawn.location - loc); //The distance between the two actors if(CollisionDistance<=400) //Checks when ever to create collision or what ever number if you have that { if (ContainsPoint(loc)) //check if this instance is within the volume { rot = MatrixGetRotator(comp.PerInstanceSMData[j].Transform); scale = MatrixGetScale(comp.PerInstanceSMData[j].Transform); CreatedBlockingMesh = Spawn(class'BlockingMesh',ac,,loc,rot); CreatedBlockingMesh.StaticMeshComponent.SetStaticMesh(comp.StaticMesh); CreatedBlockingMesh.SetDrawScale3D(scale); } } } } } } } After compiling it only says this; Warning/Error Summary--------------------- F:\Program Files\Renegade X Beta4\SDK\Development\Src\FoliageCollisionVolume\Classes\FoliageCollisionVolume.uc(46) : Warning, 'PC' : local variable used before assigned a value Interesting stuff for player log: https://forums.epicgames.com/threads/89 ... d-Material http://www.polycount.com/forum/showthread.php?t=97548 https://forums.epicgames.com/threads/74 ... r-location Quote Link to comment Share on other sites More sharing options...
Totem Arts Staff Handepsilon Posted June 17, 2015 Totem Arts Staff Share Posted June 17, 2015 It's quite a big issue. You did not define what PC is. You only tell the function that it's of a PlayerController type, but did not determine which PlayerController in the current world PC is referring to. Unfortunately I don't know how to get all PlayerControllers, except maybe with ForEach. Quote Link to comment Share on other sites More sharing options...
RoundShades Posted June 18, 2015 Share Posted June 18, 2015 It's quite a big issue. You did not define what PC is. You only tell the function that it's of a PlayerController type, but did not determine which PlayerController in the current world PC is referring to.Unfortunately I don't know how to get all PlayerControllers, except maybe with ForEach. The SBH had an if statement like: if [LocalPC.PlayerPawn == None] But that kept erroring in this code. Is that something that would help stifle this, and why couldn't it find LocalPC if so... Quote Link to comment Share on other sites More sharing options...
Totem Arts Staff yosh56 Posted June 18, 2015 Totem Arts Staff Share Posted June 18, 2015 LocalPC isn't a magic word, it's a variable that's set in the Pawn class iirc. You actually need to find and set the localpc if you're outside of a class that already has a variable for it or a function that points to it. As Hande said, you would probably need to look through Player controllers with a foreach statement. The exact syntax from this object I can't tell you without being at my computer. Quote Link to comment Share on other sites More sharing options...
RoundShades Posted June 18, 2015 Share Posted June 18, 2015 Yeah that would make sense, I thought it was a variable in another location (like Stankmod.rx_vehicle_stealth_tank) so it could be referenced externally, but it makes sense. So, could he just add a default properties field at the bottom and then a localpc? Or does he also need a foreach statement? Rudd, I suggest you search the pawnsbh for both those and see if you can figure out how to do one or both of those from looking at the code in context of the sbh. Quote Link to comment Share on other sites More sharing options...
Ruud033 Posted June 18, 2015 Author Share Posted June 18, 2015 I don't need to use the localpc.pawn.location variable persé.. I could also use some other variable that outputs a location that's relevant to a player. CameraWorldPosition for example. Any other clues on this? Edit: So I've been looking into possibilities on how to do this. - Enable rigidbody blocking (failed because I was not allowed to add this value to the foliage, said the compiler) - Spawn collision by checking the distance between actors (failed because I can't get the correct distance calculation right! Don't know how to fix this. - Spawn collision by touching the volume (still looking into this right now) Quote Link to comment Share on other sites More sharing options...
Ruud033 Posted June 20, 2015 Author Share Posted June 20, 2015 So I've gotten quite far in this already. It spawns the new dynamic actors when I walk in the zone BUT, it only destroys 1 actor (read: blocking mesh) when I leave the zone.. How can I make sure it destroys ALL created actors? Yosh spoke of a dynamic array of some sort.. Can anyone advise me on this? Every input is welcome. //============================================================================= // FoliageCollisionVolume: a vehicle collision solution // used to collide certain classes of actors // primary use is to provide collision for non-zero extent traces around static meshes // Created by Pinheiro, https://forums.epicgames.com/threads/913559-How-to-enable-collision-on-foliage // Heavily modified by Ruud033 //============================================================================= class FoliageCollisionVolume extends Volume placeable; var BlockingMesh CreatedBlockingMesh; //need dynamic array static final function vector MatrixGetScale(Matrix TM) { local Vector s; s.x = sqrt(TM.XPlane.X**2 + TM.XPlane.Y**2 + TM.XPlane.Z**2); s.y = sqrt(TM.YPlane.X**2 + TM.YPlane.Y**2 + TM.YPlane.Z**2); s.z = sqrt(TM.ZPlane.X**2 + TM.ZPlane.Y**2 + TM.ZPlane.Z**2); return s; } event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal ) { local InstancedFoliageActor ac; local InstancedStaticMeshComponent comp; local vector loc, scale; local Rotator rot; local int i, j; super.Touch(Other, OtherComp, HitLocation, HitNormal); //look for the InstancedFoliageActor foreach AllActors(class'InstancedFoliageActor',ac) { //iterate through the various foliage components for(i=0; i { comp = ac.InstancedStaticMeshComponents[i]; if (comp.StaticMesh.BodySetup != none) { //iterate through the various meshes in this component, if it has a collision model for (j=0; j { //decompose the instance's transform matrix loc = MatrixGetOrigin(comp.PerInstanceSMData[j].Transform); if (ContainsPoint(loc)) //check if this instance is within the volume { rot = MatrixGetRotator(comp.PerInstanceSMData[j].Transform); scale = MatrixGetScale(comp.PerInstanceSMData[j].Transform); CreatedBlockingMesh = Spawn(class'BlockingMesh',ac,,loc,rot); CreatedBlockingMesh.StaticMeshComponent.SetStaticMesh(comp.StaticMesh); CreatedBlockingMesh.SetDrawScale3D(scale); } } } } } } event Untouch( Actor Other ) { CreatedBlockingMesh.Destroy(); } defaultproperties { bColored=true BrushColor=(R=0,G=255,B=255,A=255) bCollideActors=true bProjTarget=true SupportedEvents.Empty SupportedEvents(0)=class'SeqEvent_Touch' } Quote Link to comment Share on other sites More sharing options...
Crnyo Posted June 21, 2015 Share Posted June 21, 2015 (edited) Not sure why code doesn't remove all spawned actors. Maybe Super.Untouch(Other) does something important behind the scenes? If so you should add it within event Untouch You could also try manually destroying all other meshes within "distance" radius of that one mesh which successfully gets destroyed upon Untouch. var int distance; event Untouch ( Actor Other) { ForEach WorldInfo.AllActors(Actor mesh) { if (mesh.IsA('BlockingMesh') && (vSizeSq(mesh.pos - CreatedBlockingMesh.pos) <= (distance**2))) { mesh.Destroy(); } } } Edited June 21, 2015 by Guest Quote Link to comment Share on other sites More sharing options...
Crnyo Posted June 21, 2015 Share Posted June 21, 2015 Here is version using DynamicArrays, it is probably faster. Search for "NEW CODE" to easily locate what I've added. //============================================================================= // FoliageCollisionVolume: a vehicle collision solution // used to collide certain classes of actors // primary use is to provide collision for non-zero extent traces around static meshes // Created by Pinheiro, https://forums.epicgames.com/threads/913559-How-to-enable-collision-on-foliage // Heavily modified by Ruud033 //============================================================================= class FoliageCollisionVolume extends Volume placeable; var BlockingMesh CreatedBlockingMesh; //need dynamic array var Array SpawnedBlockingMeshes; // NEW CODE static final function vector MatrixGetScale(Matrix TM) { local Vector s; s.x = sqrt(TM.XPlane.X**2 + TM.XPlane.Y**2 + TM.XPlane.Z**2); s.y = sqrt(TM.YPlane.X**2 + TM.YPlane.Y**2 + TM.YPlane.Z**2); s.z = sqrt(TM.ZPlane.X**2 + TM.ZPlane.Y**2 + TM.ZPlane.Z**2); return s; } event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal ) { local InstancedFoliageActor ac; local InstancedStaticMeshComponent comp; local vector loc, scale; local Rotator rot; local int i, j; super.Touch(Other, OtherComp, HitLocation, HitNormal); //look for the InstancedFoliageActor foreach AllActors(class'InstancedFoliageActor',ac) { //iterate through the various foliage components for(i=0; i { comp = ac.InstancedStaticMeshComponents[i]; if (comp.StaticMesh.BodySetup != none) { //iterate through the various meshes in this component, if it has a collision model for (j=0; j { //decompose the instance's transform matrix loc = MatrixGetOrigin(comp.PerInstanceSMData[j].Transform); if (ContainsPoint(loc)) //check if this instance is within the volume { rot = MatrixGetRotator(comp.PerInstanceSMData[j].Transform); scale = MatrixGetScale(comp.PerInstanceSMData[j].Transform); CreatedBlockingMesh = Spawn(class'BlockingMesh',ac,,loc,rot); CreatedBlockingMesh.StaticMeshComponent.SetStaticMesh(comp.StaticMesh); CreatedBlockingMesh.SetDrawScale3D(scale); SpawnedBlockingMeshes.AddItem(CreatedBlockingMesh); // NEW CODE } } } } } } // NEW CODE STARTS event Untouch( Actor Other ) { Super.Untouch(Other); ForEach SpawnedBlockingMeshes(BlockingMesh mesh) mesh.Destroy(); SpawnedBlockingMeshes.Length = 0; } // NEW CODE ENDS defaultproperties { bColored=true BrushColor=(R=0,G=255,B=255,A=255) bCollideActors=true bProjTarget=true SupportedEvents.Empty SupportedEvents(0)=class'SeqEvent_Touch' } Quote Link to comment Share on other sites More sharing options...
Crnyo Posted June 21, 2015 Share Posted June 21, 2015 I think I know why your code only deletes one blocking mesh. Spawn(x) is a function which tell engine to spawn object of class x and returns memory address of that object. When you say Y = Spawn(x); then you are giving two instructions: 1)Spawn object of class X 2)Give that address of object to Y Take a look at this: for (i=0; i < 3; i++) { SpawnedBlockingMesh = Spawn(BlockingMesh); } i=0: Engine spawns blockingmesh1 on the map and makes your SpawnedBlockingMesh point to blockingmesh1 i=1: Engine spawns blockingmesh2 and your SpawnedBlockingMesh now points to blockingmesh2 i=2: Engine spawns blockingmesh3 and SpawnedBlockingMesh now points to blockingmesh3 When you use SpawnedBlockingMesh.Delete(); Only object deleted will be the one SpawnedBlockingMesh is pointing at and that is mesh 3. You have lost your references to mesh 1 and mesh 2 because you keep overwriting SpawnedBlockingMesh with addresses of new objects. That is why you need to use dynamic arrays. Instead of SpawnedBlockingMesh = Spawn(BlockingMesh) use var Array SpawnedBlockingMeshArray; ... for (i=0; i<3; i++) { SpawnedBlockingMeshArray.AddItem(Spawn(BlockingMesh)); } Quote Link to comment Share on other sites More sharing options...
Totem Arts Staff yosh56 Posted June 21, 2015 Totem Arts Staff Share Posted June 21, 2015 ^ That guy sums up what I was telling you on TS, Ruud. Sorry I couldn't go in to more detail, it was 5 in the morning and I was struggling to form coherent sentences, let alone explain how to use dynamic arrays. Quote Link to comment Share on other sites More sharing options...
Ruud033 Posted June 22, 2015 Author Share Posted June 22, 2015 That's awesome (both of you)! I'll test this code tonight! Very excited about it. Thanks for the help Crnyo, I'll mention you in the top section. You delivered a critical piece of code there, I wasn't able to make it Quote Link to comment Share on other sites More sharing options...
Ruud033 Posted June 22, 2015 Author Share Posted June 22, 2015 Your current code does not work sadly I'm trying to figure out what's happening. The issue seems to be in line 69. F:\Program Files\Renegade X Beta4\SDK\Development\Src\FoliageCollisionVolume\Classes\FoliageCollisionVolume.uc(69) : Error, Bad or missing expression for token: BlockingMesh, in 'foreach array'Failure - 1 error(s), 0 warning(s) Execution of commandlet took: 4.63 seconds [jun 22, 7:19 ] COMMANDLET 'UDK.exe make' FAILED Maybe you've done it wrong there? check out this: https://udn.epicgames.com/Three/UnrealS ... ators.html https://udn.epicgames.com/Three/UnrealS ... ayIterator http://wiki.beyondunreal.com/Dynamic_arrays Not sure what is going on there. //============================================================================= // FoliageCollisionVolume: a vehicle collision solution // used to collide certain classes of actors // primary use is to provide collision for non-zero extent traces around static meshes // Created by Pinheiro, https://forums.epicgames.com/threads/913559-How-to-enable-collision-on-foliage // Heavily modified by Ruud033 //============================================================================= class FoliageCollisionVolume extends Volume placeable; var BlockingMesh CreatedBlockingMesh; var Array SpawnedBlockingMeshes; static final function vector MatrixGetScale(Matrix TM) { local Vector s; s.x = sqrt(TM.XPlane.X**2 + TM.XPlane.Y**2 + TM.XPlane.Z**2); s.y = sqrt(TM.YPlane.X**2 + TM.YPlane.Y**2 + TM.YPlane.Z**2); s.z = sqrt(TM.ZPlane.X**2 + TM.ZPlane.Y**2 + TM.ZPlane.Z**2); return s; } //Search for each tree apart, the code goes trough the volume and searches each tree. event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal ) { local InstancedFoliageActor ac; local InstancedStaticMeshComponent comp; local vector loc, scale; local Rotator rot; local int i, j; super.Touch(Other, OtherComp, HitLocation, HitNormal); //look for the InstancedFoliageActor foreach AllActors(class'InstancedFoliageActor',ac) { //iterate through the various foliage components for(i=0; i { comp = ac.InstancedStaticMeshComponents[i]; if (comp.StaticMesh.BodySetup != none) { //iterate through the various meshes in this component, if it has a collision model for (j=0; j { //decompose the instance's transform matrix loc = MatrixGetOrigin(comp.PerInstanceSMData[j].Transform); if (ContainsPoint(loc)) //check if this instance is within the volume { rot = MatrixGetRotator(comp.PerInstanceSMData[j].Transform); scale = MatrixGetScale(comp.PerInstanceSMData[j].Transform); CreatedBlockingMesh = Spawn(class'BlockingMesh',ac,,loc,rot); CreatedBlockingMesh.StaticMeshComponent.SetStaticMesh(comp.StaticMesh); CreatedBlockingMesh.SetDrawScale3D(scale); SpawnedBlockingMeshes.AddItem(CreatedBlockingMesh); } } } } } } //Destroy the spawned meshes once untouched event Untouch( Actor Other ) { Super.Untouch(Other); ForEach SpawnedBlockingMeshes(BlockingMesh, mesh) { mesh.Destroy(); SpawnedBlockingMeshes.Length = 0; } } defaultproperties { bColored=true BrushColor=(R=0,G=255,B=255,A=255) bCollideActors=true bProjTarget=true SupportedEvents.Empty SupportedEvents(0)=class'SeqEvent_Touch' } Edit: also posted on UDK forums https://forums.epicgames.com/threads/99 ... st31929327 Quote Link to comment Share on other sites More sharing options...
Totem Arts Staff Handepsilon Posted June 22, 2015 Totem Arts Staff Share Posted June 22, 2015 You forgot Class in foreach SpawnedBlockingVolume (see allactors foreach for reference) Quote Link to comment Share on other sites More sharing options...
Ruud033 Posted June 22, 2015 Author Share Posted June 22, 2015 when doing this: //Destroy the spawned meshes once untouched event Untouch( Actor Other ) { Super.Untouch(Other); ForEach SpawnedBlockingMeshes(class'BlockingMesh', mesh) { mesh.Destroy(); SpawnedBlockingMeshes.Length = 0; } } I get: ---------------------F:\Program Files\Renegade X Beta4\SDK\Development\Src\FoliageCollisionVolume\Classes\FoliageCollisionVolume.uc(70) : Error, 'foreach array': Expecting a variable, not a constant Failure - 1 error(s), 0 warning(s) Execution of commandlet took: 4.98 seconds [jun 22, 10:24 ] COMMANDLET 'UDK.exe make' FAILED Quote Link to comment Share on other sites More sharing options...
Totem Arts Staff Handepsilon Posted June 22, 2015 Totem Arts Staff Share Posted June 22, 2015 Hmmmmm try foreach spawnedblockingmeshes(mesh) or. add local integer (i) and replace that foreach with for (i = 0; i > SpawnedBlockingMesh.length; i++) { SpawnedBlockingMesh[i].Destroy(); } SpawnedBlockingMesh.Length = 0; Quote Link to comment Share on other sites More sharing options...
Totem Arts Staff yosh56 Posted June 23, 2015 Totem Arts Staff Share Posted June 23, 2015 when doing this: //Destroy the spawned meshes once untouched event Untouch( Actor Other ) { Super.Untouch(Other); ForEach SpawnedBlockingMeshes(class'BlockingMesh', mesh) { mesh.Destroy(); SpawnedBlockingMeshes.Length = 0; } } I get: ---------------------F:\Program Files\Renegade X Beta4\SDK\Development\Src\FoliageCollisionVolume\Classes\FoliageCollisionVolume.uc(70) : Error, 'foreach array': Expecting a variable, not a constant Failure - 1 error(s), 0 warning(s) Execution of commandlet took: 4.98 seconds [jun 22, 10:24 ] COMMANDLET 'UDK.exe make' FAILED Basically what Hande said, as he beat me to it. When you iterate through a dynamic array with foreach, it only needs an out variable to set something to. The dynamic array can only be ONE type of thing, so it doesn't need you to tell it what kind of thing to look for. Quote Link to comment Share on other sites More sharing options...
Ruud033 Posted June 23, 2015 Author Share Posted June 23, 2015 Tried your script, also added a vehicle check. Thanks for this idea Handepsilon, I only need to spawn collision when ever a VEHICLE hits the volume, infantry does not matter since they already collide... all the sudden we have a LOT of performance gain over time :D:D since the server does not have to spawn collision for infantry. Sadly, the collision does not remove itself... I have bNoDelete=false in the BlockingMesh.uc set, so that should not be an issue for Destroy() FoliageCollisionVolume.uc //============================================================================= // FoliageCollisionVolume: a vehicle collision solution // used to collide certain classes of actors // primary use is to provide collision for non-zero extent traces around static meshes // Created by Pinheiro, https://forums.epicgames.com/threads/913559-How-to-enable-collision-on-foliage // Heavily modified by Ruud033 //============================================================================= class FoliageCollisionVolume extends Volume placeable; var BlockingMesh CreatedBlockingMesh; var Array SpawnedBlockingMeshes; static final function vector MatrixGetScale(Matrix TM) { local Vector s; s.x = sqrt(TM.XPlane.X**2 + TM.XPlane.Y**2 + TM.XPlane.Z**2); s.y = sqrt(TM.YPlane.X**2 + TM.YPlane.Y**2 + TM.YPlane.Z**2); s.z = sqrt(TM.ZPlane.X**2 + TM.ZPlane.Y**2 + TM.ZPlane.Z**2); return s; } //Search for each tree apart, the code goes trough the volume and searches each tree. event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal ) { local InstancedFoliageActor ac; local InstancedStaticMeshComponent comp; local vector loc, scale; local Rotator rot; local int i, j; super.Touch(Other, OtherComp, HitLocation, HitNormal); If(Other.IsA('Vehicle')) { //look for the InstancedFoliageActor foreach AllActors(class'InstancedFoliageActor',ac) { //iterate through the various foliage components for(i=0; i { comp = ac.InstancedStaticMeshComponents[i]; if (comp.StaticMesh.BodySetup != none) { //iterate through the various meshes in this component, if it has a collision model for (j=0; j { //decompose the instance's transform matrix loc = MatrixGetOrigin(comp.PerInstanceSMData[j].Transform); if (ContainsPoint(loc)) //check if this instance is within the volume { rot = MatrixGetRotator(comp.PerInstanceSMData[j].Transform); scale = MatrixGetScale(comp.PerInstanceSMData[j].Transform); CreatedBlockingMesh = Spawn(class'BlockingMesh',ac,,loc,rot); CreatedBlockingMesh.StaticMeshComponent.SetStaticMesh(comp.StaticMesh); CreatedBlockingMesh.SetDrawScale3D(scale); SpawnedBlockingMeshes.AddItem(Spawn(class'BlockingMesh')); } } } } } } } //Destroy the spawned meshes once untouched event Untouch( Actor Other ) { local int i; Super.Untouch(Other); for(i=0; i > SpawnedBlockingMeshes.Length; i++) { SpawnedBlockingMeshes[i].Destroy();//if bNoDelete is set to false in defaultproperties; this deletes it SpawnedBlockingMeshes.Remove(i--,1); } SpawnedBlockingMeshes.Length = 0; } defaultproperties { bColored=true BrushColor=(R=0,G=255,B=255,A=255) bCollideActors=true SupportedEvents.Empty SupportedEvents(0)=class'SeqEvent_Touch' } BlockingMesh.uc //============================================================================= // FoliageCollisionVolume: a vehicle collision solution // used to collide certain classes of actors // primary use is to provide collision for non-zero extent traces around static meshes // Created by Pinheiro, https://forums.epicgames.com/threads/913559-How-to-enable-collision-on-foliage // Modified by Ruud033 //============================================================================= class BlockingMesh extends DynamicSMActor_Spawnable; defaultproperties { Begin Object Name=StaticMeshComponent0 HiddenGame = true //we don't wanna draw this, it's just used to test collision BlockRigidBody=true //DynamicSMActors have collision disabled by default CastShadow=false MaxDrawDistance = 500 bAllowCullDistanceVolume=true AlwaysLoadOnServer=false End object bCollideActors=true //same here bTickIsDisabled = true //greatly improves performance on the game thread bStatic=false bNoDelete=false } Quote Link to comment Share on other sites More sharing options...
Totem Arts Staff Handepsilon Posted June 23, 2015 Totem Arts Staff Share Posted June 23, 2015 Ok, let's revamp your script. All modifications are in bold //============================================================================= // FoliageCollisionVolume: a vehicle collision solution // used to collide certain classes of actors // primary use is to provide collision for non-zero extent traces around static meshes // Created by Pinheiro, https://forums.epicgames.com/threads/913559-How-to-enable-collision-on-foliage // Heavily modified by Ruud033 //============================================================================= class FoliageCollisionVolume extends Volume placeable; var BlockingMesh CreatedBlockingMesh; var Array SpawnedBlockingMeshes; [b]var bool bBlockersHaveSpawned //Check if blockers have already spawned. If it has, no need to spawn more[/b] [b]var Array VehiclesInVolume;[/b] static final function vector MatrixGetScale(Matrix TM) { local Vector s; s.x = sqrt(TM.XPlane.X**2 + TM.XPlane.Y**2 + TM.XPlane.Z**2); s.y = sqrt(TM.YPlane.X**2 + TM.YPlane.Y**2 + TM.YPlane.Z**2); s.z = sqrt(TM.ZPlane.X**2 + TM.ZPlane.Y**2 + TM.ZPlane.Z**2); return s; } //Search for each tree apart, the code goes trough the volume and searches each tree. event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal ) { local InstancedFoliageActor ac; local InstancedStaticMeshComponent comp; local vector loc, scale; local Rotator rot; local int i, j; super.Touch(Other, OtherComp, HitLocation, HitNormal); If(Other.IsA('Vehicle')) { [b]VehiclesInVolume.AddItem(Vehicle(Other)); if(!bBlockersHaveSpawned) { bBlockersHaveSpawned = true;[/b] //look for the InstancedFoliageActor foreach AllActors(class'InstancedFoliageActor',ac) { //iterate through the various foliage components for(i=0; i { comp = ac.InstancedStaticMeshComponents[i]; if (comp.StaticMesh.BodySetup != none) { //iterate through the various meshes in this component, if it has a collision model for (j=0; j { //decompose the instance's transform matrix loc = MatrixGetOrigin(comp.PerInstanceSMData[j].Transform); if (ContainsPoint(loc)) //check if this instance is within the volume { rot = MatrixGetRotator(comp.PerInstanceSMData[j].Transform); scale = MatrixGetScale(comp.PerInstanceSMData[j].Transform); CreatedBlockingMesh = Spawn(class'BlockingMesh',ac,,loc,rot); CreatedBlockingMesh.StaticMeshComponent.SetStaticMesh(comp.StaticMesh); CreatedBlockingMesh.SetDrawScale3D(scale); SpawnedBlockingMeshes.AddItem(Spawn(class'BlockingMesh')); } } } } } } } } //Destroy the spawned meshes once untouched event Untouch( Actor Other ) { local int i; Super.Untouch(Other); [b]for(i=0; i < VehiclesInVolume.Length; i++) { if(Vehicle(Other) == VehiclesInVolume[i]) VehiclesInVolume.RemoveItem(i--, 1); }[/b] [b] if(VehiclesInVolume.Length <= 0) {[/b] for(i=0; i [b]<[/b] SpawnedBlockingMeshes.Length; i++) { SpawnedBlockingMeshes[i].Destroy();//if bNoDelete is set to false in defaultproperties; this deletes it SpawnedBlockingMeshes.Remove(i--,1); [b]// Hande's note : This is not necessary as the below function will automatically empty the array[/b] } SpawnedBlockingMeshes.Length = 0; [b]bBlockersHaveSpawned = false;[/b] [b]}[/b] } defaultproperties { bColored=true BrushColor=(R=0,G=255,B=255,A=255) bCollideActors=true SupportedEvents.Empty SupportedEvents(0)=class'SeqEvent_Touch' } Something like this. Just fix things that needs to be fixed EDIT : Replace : for(i=0; i < VehiclesInVolume.Length; i++) { if(Vehicle(Other) == VehiclesInVolume[i]) VehiclesInVolume.RemoveItem(i--, 1); } To : VehiclesInVolume.RemoveItem(Vehicle(Other)); Quote Link to comment Share on other sites More sharing options...
Ruud033 Posted June 23, 2015 Author Share Posted June 23, 2015 New script update: Delete issue still persists.. It won't delete the actors once Untouch() FoliageCollisionVolume.uc //============================================================================= // FoliageCollisionVolume: a vehicle collision solution // used to collide certain classes of actors // primary use is to provide collision for non-zero extent traces around static meshes // Created by Pinheiro, https://forums.epicgames.com/threads/91 ... on-foliage // Heavily modified by Ruud033 & Handepsilon //============================================================================= class FoliageCollisionVolume extends Volume placeable; var BlockingMesh CreatedBlockingMesh; var Array SpawnedBlockingMeshes; var bool bBlockersHaveSpawned; //Check if blockers have already spawned. If it has, no need to spawn more var Array VehiclesInVolume; static final function vector MatrixGetScale(Matrix TM) { local Vector s; s.x = sqrt(TM.XPlane.X**2 + TM.XPlane.Y**2 + TM.XPlane.Z**2); s.y = sqrt(TM.YPlane.X**2 + TM.YPlane.Y**2 + TM.YPlane.Z**2); s.z = sqrt(TM.ZPlane.X**2 + TM.ZPlane.Y**2 + TM.ZPlane.Z**2); return s; } //Search for each tree apart, the code goes trough the volume and searches each tree. event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal ) { local InstancedFoliageActor ac; local InstancedStaticMeshComponent comp; local vector loc, scale; local Rotator rot; local int i, j; super.Touch(Other, OtherComp, HitLocation, HitNormal); If(Other.IsA('Vehicle')) { VehiclesInVolume.AddItem(Vehicle(Other)); if(!bBlockersHaveSpawned) { bBlockersHaveSpawned = true; //look for the InstancedFoliageActor foreach AllActors(class'InstancedFoliageActor',ac) { //iterate through the various foliage components for(i=0; i { comp = ac.InstancedStaticMeshComponents[i]; if (comp.StaticMesh.BodySetup != none) { //iterate through the various meshes in this component, if it has a collision model for (j=0; j { //decompose the instance's transform matrix loc = MatrixGetOrigin(comp.PerInstanceSMData[j].Transform); if (ContainsPoint(loc)) //check if this instance is within the volume { rot = MatrixGetRotator(comp.PerInstanceSMData[j].Transform); scale = MatrixGetScale(comp.PerInstanceSMData[j].Transform); CreatedBlockingMesh = Spawn(class'BlockingMesh',ac,,loc,rot); CreatedBlockingMesh.StaticMeshComponent.SetStaticMesh(comp.StaticMesh); CreatedBlockingMesh.SetDrawScale3D(scale); SpawnedBlockingMeshes.AddItem(Spawn(class'BlockingMesh')); } } } } } } } } //Destroy the spawned meshes once untouched event Untouch( Actor Other ) { local int i; Super.Untouch(Other); VehiclesInVolume.RemoveItem(Vehicle(Other)); if(VehiclesInVolume.Length <= 0) { for(i=0; i < SpawnedBlockingMeshes.Length; i++) { SpawnedBlockingMeshes[i].Destroy();//if bNoDelete is set to false in defaultproperties; this deletes it // Ok removed SpawnedBlockingMeshes.Remove(i--,1); // Hande's note : This is not necessary as the below function will automatically empty the array } SpawnedBlockingMeshes.Length = 0; bBlockersHaveSpawned = false; } } defaultproperties { bColored=true BrushColor=(R=0,G=255,B=255,A=255) bCollideActors=true SupportedEvents.Empty SupportedEvents(0)=class'SeqEvent_Touch' } Quote Link to comment Share on other sites More sharing options...
Ruud033 Posted June 23, 2015 Author Share Posted June 23, 2015 Testing latest script now, seems to be working. Quote Link to comment Share on other sites More sharing options...
Ruud033 Posted June 23, 2015 Author Share Posted June 23, 2015 It works perfectly. BlockingMesh.uc //============================================================================= // FoliageCollisionVolume: a vehicle collision solution // used to collide certain classes of actors // primary use is to provide collision for non-zero extent traces around static meshes // Created by Pinheiro, https://forums.epicgames.com/threads/913559-How-to-enable-collision-on-foliage // Modified by Ruud033 //============================================================================= class BlockingMesh extends DynamicSMActor_Spawnable; defaultproperties { Begin Object Name=StaticMeshComponent0 HiddenGame = true //we don't wanna draw this, it's just used to test collision BlockRigidBody=true //DynamicSMActors have collision disabled by default CastShadow=false MaxDrawDistance = 500 bAllowCullDistanceVolume=true AlwaysLoadOnServer=false End object bCollideActors=true //same here bTickIsDisabled = true //greatly improves performance on the game thread bStatic=false bNoDelete=false } FoliageCollisionVolume.uc //============================================================================= // FoliageCollisionVolume: a vehicle collision solution // used to collide certain classes of actors // primary use is to provide collision for non-zero extent traces around static meshes // Created by Pinheiro, https://forums.epicgames.com/threads/91 ... on-foliage // Heavily modified by Ruud033 & Handepsilon // Thanks Crnyo and nameloc for the additional help //============================================================================= class FoliageCollisionVolume extends Volume placeable; var BlockingMesh CreatedBlockingMesh; var Array SpawnedBlockingMeshes; var bool bBlockersHaveSpawned; //Check if blockers have already spawned. If it has, no need to spawn more var Array VehiclesInVolume; static final function vector MatrixGetScale(Matrix TM) { local Vector s; s.x = sqrt(TM.XPlane.X**2 + TM.XPlane.Y**2 + TM.XPlane.Z**2); s.y = sqrt(TM.YPlane.X**2 + TM.YPlane.Y**2 + TM.YPlane.Z**2); s.z = sqrt(TM.ZPlane.X**2 + TM.ZPlane.Y**2 + TM.ZPlane.Z**2); return s; } //Search for each tree apart, the code goes trough the volume and searches each tree. event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal ) { local InstancedFoliageActor ac; local InstancedStaticMeshComponent comp; local vector loc, scale; local Rotator rot; local int i, j; super.Touch(Other, OtherComp, HitLocation, HitNormal); If(Other.IsA('Vehicle')) { VehiclesInVolume.AddItem(Vehicle(Other)); if(!bBlockersHaveSpawned) { bBlockersHaveSpawned = true; //look for the InstancedFoliageActor foreach AllActors(class'InstancedFoliageActor',ac) { //iterate through the various foliage components for(i=0; i { comp = ac.InstancedStaticMeshComponents[i]; if (comp.StaticMesh.BodySetup != none) { //iterate through the various meshes in this component, if it has a collision model for (j=0; j { //decompose the instance's transform matrix loc = MatrixGetOrigin(comp.PerInstanceSMData[j].Transform); if (ContainsPoint(loc)) //check if this instance is within the volume { rot = MatrixGetRotator(comp.PerInstanceSMData[j].Transform); scale = MatrixGetScale(comp.PerInstanceSMData[j].Transform); CreatedBlockingMesh = Spawn(class'BlockingMesh',ac,,loc,rot); CreatedBlockingMesh.StaticMeshComponent.SetStaticMesh(comp.StaticMesh); CreatedBlockingMesh.SetDrawScale3D(scale); SpawnedBlockingMeshes.AddItem(CreatedBlockingMesh); } } } } } } } } //Destroy the spawned meshes once untouched event Untouch( Actor Other ) { local int i; Super.Untouch(Other); VehiclesInVolume.RemoveItem(Vehicle(Other)); if(VehiclesInVolume.Length <= 0) { for(i=0; i < SpawnedBlockingMeshes.Length; i++) { SpawnedBlockingMeshes[i].Destroy();//if bNoDelete is set to false in defaultproperties; this deletes it // Ok removed SpawnedBlockingMeshes.Remove(i--,1); // Hande's note : This is not necessary as the below function will automatically empty the array } SpawnedBlockingMeshes.Length = 0; bBlockersHaveSpawned = false; } } defaultproperties { bColored=true BrushColor=(R=0,G=255,B=255,A=255) bCollideActors=true SupportedEvents.Empty SupportedEvents(0)=class'SeqEvent_Touch' } Quote Link to comment Share on other sites More sharing options...
Totem Arts Staff Handepsilon Posted July 10, 2015 Totem Arts Staff Share Posted July 10, 2015 I'm not sure but we had a 5 vs 5 in EKT, ping spiked up all in a sudden there. If I compile the latest code right, this could be a problem... Quote Link to comment Share on other sites More sharing options...
Ruud033 Posted July 10, 2015 Author Share Posted July 10, 2015 In my map? If it was in my map that could be! I have not uploaded the optimised version yet as I have to add stuff to it and what not before I bring it out again.. Oh well, I'll build all and re-upload what I have now. Lots of changes already so.. If it was in your map you might want to ask yourself if you have set the size of the volumes correctly Quote Link to comment Share on other sites More sharing options...
Totem Arts Staff Handepsilon Posted July 10, 2015 Totem Arts Staff Share Posted July 10, 2015 It's your map, with your latest code compiled in (referencing from your last post) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.