Need help with trace function for decal placement

Discussions about Coding and Scripting

Need help with trace function for decal placement

Postby JackGriffin » Thu Nov 08, 2018 3:34 pm

I'm very stuck on this and I'd like some help if you have the time.

A brief backstory:
In my contest submission I have graffiti placed randomly throughout the level. This is accomplished by spawning invisible rockets that fly until they hit a wall that is around perpendicular to the game floor. Basically any normal wall surface. Once they hit they spawn a random graffiti and this remains throughout the game. Total number is capped and configurable by the admin.

Here is what I mean:
Shot0004.jpg


It works great but often the decal ends up being partially on the wall or in a bad spot.

What I would like to happen is that when the rocket hits the wall it does a fast set of traces. Up, down, left, right and looks to see if the wall is still there in a 128X128 box. This should eliminate the vast majority of problems.

I've scoured the internet for a good tutorial on the maths and implementation of how to do this tracing but I can't figure it out. Does anyone know a good place to learn how to do this or want to spend a little bit explaining to me how to code the checks?
You maybe ought to go ahead and add /s to whatever I posted above just to be safe.
User avatar
JackGriffin
Godlike
 
Posts: 3545
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: Hack coder


Re: Need help with trace function for decal placement

Postby JackGriffin » Fri Nov 09, 2018 2:35 am

Thank you Higor.

I've been pouring over the "AroundCylinder" check and it's starting to become clear how to do this. Your code checks for things to be clear but how would I also check to make sure the wall is still below? What I mean is....say the hitlocation is near the edge of a doorway. If I understand your code it would pass but I also need to make sure the same wall is underneath all the way around.
You maybe ought to go ahead and add /s to whatever I posted above just to be safe.
User avatar
JackGriffin
Godlike
 
Posts: 3545
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: Hack coder

Re: Need help with trace function for decal placement

Postby Higor » Fri Nov 09, 2018 8:21 am

The key here is being able to rotate normals by 90º.

I'll give you a clue (it's cheating because it's using Rotator, but whatever).
Hit the wall, get the normal, the opposite direction of that normal aims at the wall.
Convert said opposite to rotator, do
Code: Select all
GetAxes( rotator(-HitNormal), X, Y, Z);

If we consider the wall regardless of it's slant.
X should be almost identical to -HitNormal
Y aims to the right (or left?, doesn't matter)
Z aims up (wall direction).

These 3 normals create a coordinate system.
We need an origin.
Origin shouldn't be ON the wall, but a bit away from it:
Code: Select all
Origin = HitLocation + HitNormal;


Now that you have an origin, you can select points on said coordinate system.
Let's see... I'm going to select N*M additional points, drawing a matrix around the hit location, hit location may even be double checked because of this!!!
Least effort case is N=2, M=2.
SpriteX is the horizontal size, SpriteY is vertical size.
Code: Select all
local float yOffset, zOffset;
local int i, j;
for ( i=0 ; i<N ; i++)
{
    yOffset = (-SpriteX)*0.5 + SpriteX * i / (N-1);
    for ( j=0 ; j<M ; j++ )
    {
        zOffset = (-SpriteY)*0.5 + SpriteY * j / (M-1);
        StartTrace = Origin + Y * yOffset + Z * zOffset;
        EndTrace = StartTrace + X * 3; //Bigger distance, bigger tolerance for failure.
        //First, trace from Origin to StartTrace, if blocked, wall is concave (FAIL!)
        //Then, trace from StartTrace to EndTrace, if blocked, wall is flat (or almost flat) (SUCCESS!)
    }
}


That algorithm should work for any N,M combinations.
Higor
Godlike
 
Posts: 1639
Joined: Sun Mar 04, 2012 6:47 pm

Re: Need help with trace function for decal placement

Postby JackGriffin » Fri Nov 09, 2018 12:46 pm

Oh man, it finally clicked. Thank you! Figuring the 90 degree turn relative to the hitnormal was where I was stuck.

That's something I didn't know either was that the actual hitnormal was slightly above the surface and not on the surface. I assumed it was the intersecting point.

I'm not sure how much time you or someone else wanted to throw at this but there is very little actual vector information out there geared towards uscript. Your short explanation explains more than I was able to find googling. I'm sure there are more guys like me who never learned vector math in school and don't just know what wallnormal and hitnormal are. A bit of a dive into how it works would be very welcome.
You maybe ought to go ahead and add /s to whatever I posted above just to be safe.
User avatar
JackGriffin
Godlike
 
Posts: 3545
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: Hack coder

Re: Need help with trace function for decal placement

Postby Feralidragon » Fri Nov 09, 2018 1:33 pm

Well, generally developers do not need to do many vector maths to begin with, but in this case the GetAxes is essentially a function which gets the 3D rotation matrix from an Euler rotation.
A 3D rotation matrix is 3x3, each line corresponding directly to an axis, that's why it outputs 3 vectors: X, Y and Z.

If you think of a cube in 3D space, like this:
Image
each one of the axis in that picture is pretty much each axis that you get from GetAxes (each one normalized, with a length of 1).

If you imagine the cube rotating in any way, the axis remain aligned with the cube, and these are the axis you get, hence each one of them representing always a specific direction relative to the rotation of the object itself: front-back (X), left-right (Y), up-down (Z).
From here, since these 3 axis represent a 3D rotation matrix, you can do things like matrix multiplication between 2 matrices so you can get a rotation rotated by another rotation, but I won't dwelve into the details of this (matrix multiplication is not as simple as scalar multiplication, it has a specific recipe to do it, and is not commutative, so the order of the matrices matter in the end result).

From there, you can covert the 3D rotation matrix back into a normal (Euler) rotation using OrthoRotation (if I am not mistaken).
But generally you don't need to go this far and you can just use the << and >> operators for this, to rotate vectors by rotators.

The main "problem" with the actual math, and other engines, is that Unreal Engine is actually the weird guy in the room, since generally the Y axis represents up-down, and not left-right (just like in 2D), while the Z axis represents the 3D depth (hence the graphical rendering depth buffer being called Z-buffer, because the Z axis is depth, and not up-down).
So whenever you see any online explanation on how the 3D coordination works, you have to switch Y by Z (and Z by Y) in your mind, for it to start to make sense in your mind.

I am not an expert on the mathematical side of this though, but as far as these functions go, they're simpler than they look at first, all you need to do is visualize it like in the image above.
User avatar
Feralidragon
Godlike
 
Posts: 4954
Joined: Wed Feb 27, 2008 6:24 pm
Location: Liandri
Personal rank: Work In Progress

Re: Need help with trace function for decal placement

Postby JackGriffin » Fri Nov 09, 2018 2:59 pm

all you need to do is visualize it like in the image above.

Swear to God you should see my desk right now. I've hand-sketched wall/floor layouts like your cube and labeled everything to make it clear in my mind. You are right, once you strip away the code and just look at the vectors involved it's not really that bad. Hell, if I can begin to understand it then literally anyone can.

I wrote a function if you guys want to critique it. The graffitilight is just a small light actor to slightly illuminate graffiti:
Code: Select all
   function TraceDecal()
   {
      local float yOffset, zOffset;
      local int i, j, N, M, SpriteX, SpriteY;
      local vector X, Y, Z, Origin, HitNormal, HitLocation, StartTrace, EndTrace;
      local actor Other;
      local bool DecalClear;
      local GraffitiLight b;

      GetAxes( rotator(-HitNormal), X, Y, Z);
      Origin = HitLocation + HitNormal;
      DecalClear = True;
      N = 2;
      M = 2;
      SpriteX = 128;
      SpriteY = 128;

      for ( i=0 ; i<N ; i++)
      {
         yOffset = (-SpriteX)*0.5 + SpriteX * i / (N-1);
           for ( j=0 ; j<M ; j++ )
           {
            zOffset = (-SpriteY)*0.5 + SpriteY * j / (M-1);
            StartTrace = Origin;
            EndTrace =  Origin + Y * yOffset + Z * zOffset;
            Other = Trace(HitLocation, HitNormal, EndTrace, StartTrace, true);
            if (Other != none)
            {
               log("Decal blocked");
               log(Other);
               DecalClear = False;
                 return;
            }
            else
            {
               StartTrace = Origin + Y * yOffset + Z * zOffset;
               EndTrace = StartTrace + X * 3;
               Other = Trace(HitLocation, HitNormal, EndTrace, StartTrace, true);
               if (Other != none)
               {
                  log("Decal success!");
                   DecalClear = True;
               }
               else
                  DecalClear = False;
            }
         }
         if(DecalClear)
         {
              Spawn(ExplosionDecal,self,,Location, rotator(HitNormal));
              b = Spawn(class'GraffitiLight',self,,Location + HitNormal*32);
              b.remoterole=ROLE_simulatedproxy;
         }
      }
   }


The code compiles but it's failing so I added the log lines. This is my output:
ScriptLog: Decal blocked
ScriptLog: DM-Deck16][.LevelInfo0
ScriptLog: Decal blocked
ScriptLog: DM-Deck16][.LevelInfo0

but I can't see why it's failing the first trace. Shouldn't that be running along the wall face to the decal edge? BTW, I know this function should be written better and not hard-coded with set variables but I'm learning a lot here and I need it to be solid in my mind before I complicate it.
You maybe ought to go ahead and add /s to whatever I posted above just to be safe.
User avatar
JackGriffin
Godlike
 
Posts: 3545
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: Hack coder

Re: Need help with trace function for decal placement

Postby Higor » Fri Nov 09, 2018 6:01 pm

You need to obtain HitNormal and HitLocation with a trace or a HitWall event.
Higor
Godlike
 
Posts: 1639
Joined: Sun Mar 04, 2012 6:47 pm

Re: Need help with trace function for decal placement

Postby JackGriffin » Sat Nov 10, 2018 4:56 pm

Ah, ok. I had called TraceDecal() in Hitwall when I should have just nested all this code into that function. Thanks again for your help, I'm really excited to learn this properly and to be able to apply it.

Edit: got the code properly nested but there are times when the graffiti goes partially off the bsp like this:
Shot0016.jpg


I have been logging everything to figure out why but I think it's because I set:
HitLocation = Location;
in HitWall. That's not precise enough is it?
You maybe ought to go ahead and add /s to whatever I posted above just to be safe.
User avatar
JackGriffin
Godlike
 
Posts: 3545
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: Hack coder

Re: Need help with trace function for decal placement

Postby Chris » Mon Nov 12, 2018 7:05 am

You can easily replace the Trace() with FastTrace.
If you have decided how many tests you want to make, you can unroll Higor's loops and simplify the equations.

Origin + (Y * SomeSizeVector) will give you the center of the edge of your collision matrix. Negate (Y * SomeSizeVector) to get the opposite direction (left vs right). In this case Y is right and left. Remember to multiply with all 3 components since they're relative.

To get the perpendicular corners of the matrix, do
Origin + (Y * SomeSizeVector) + (Z * SomeSizeVector)
Origin + -(Y * SomeSizeVector) + (Z * SomeSizeVector)
Origin + (Y * SomeSizeVector) + -(Z * SomeSizeVector)
Origin + -(Y * SomeSizeVector) + -(Z * SomeSizeVector)

Those will be your StartTraces for each corner. Then your EndTrace will be StartTrace + (X * DepthVector) (could be 3 like in Higor's example. If any of the Traces return false, then your matrix is over the edge of your wall (or wall is not straight. For better accuracy you should do 8 traces
One in each corner and one on the center of each edge.
That will still not account for HitLocations that are in, say a window with an edge around it. To test for that you would need 1-2 more traces, and trace the hypothenus (top corner to bottom corner)

Sorry for any mistakes, I'm writing this on my phone while sitting on the train :ironic:
Chris
Experienced
 
Posts: 113
Joined: Mon Nov 24, 2014 9:27 am

Re: Need help with trace function for decal placement

Postby Feralidragon » Mon Nov 12, 2018 12:29 pm

Yes, you can use fast tracing for this since the decision is binary (either it hits or it doesn't) and you don't really need the hit output information.

However, it wouldn't be just a single trace for each corner/edge, it would be 2, so 8 traces is the minimum for either 4 corners OR 4 edge centers.
A while ago I made the following diagram (posting it now so it makes more sense to everyone what is being discussed here):
decal_proj.jpg


As you can see, you need to trace to the sides first to at least account for any corners that may hide the decal, and only then you can do the traces you mentioned.
So to do the corners and edges, you actually need to do 16 traces in total (or fast traces in this case).

Also yeah, if you want a better resolution, you just need to add more and more traces within the area of the decal, meaning that to have pretty much perfect accuracy in these tests, you need about the double of as many traces as you have pixels in the decal you want to test, which isn't feasible, so probably the corners and edges should be more than enough for what is wanted here, as there will be always corner cases even if you add a few more around, simply due to the lack of tracing area resolution.
User avatar
Feralidragon
Godlike
 
Posts: 4954
Joined: Wed Feb 27, 2008 6:24 pm
Location: Liandri
Personal rank: Work In Progress

Re: Need help with trace function for decal placement

Postby JackGriffin » Mon Nov 12, 2018 4:11 pm

Under suggestion from Ferali I removed this feature from my contest entry and I'm attempting to fix it apart from the rest of the game. I spent about 10 hours on this yesterday and it's incredibly frustrating. I keep thinking I have it and then I realize I just don't once I work back through the logic to see what's wrong. It's so easy to miss little things on something like this.

Ferali gave me some perfectly appropriate advice last night. He told me to stop trying to solve the big picture. Instead break things down into smaller, constituent parts. Work on the first part then move on to the second. In doing that I was able to walk from unsolved to very close to solved on this problem.

In case you want to see how I did this, here's the code. It's long but it's full of logging lines so I can see what is going on every step of the way. Logging outputs like this:
ScriptLog: PING
ScriptLog: Firing!
ScriptLog: NavPoint : 17
ScriptLog: Found the nav point
ScriptLog: HitActor: DM-StalwartXL.LevelInfo0
ScriptLog: Hit the level here : -335.623627,511.587708,102.062286
ScriptLog: Origin location: -335.623627,510.587708,102.062286
ScriptLog: Start Trace1 : -335.623627,510.587708,102.062286
ScriptLog: End Trace1 : -399.623627,510.612244,166.062286
ScriptLog: 2nd pass Start Trace1 : -399.623627,510.612244,166.062286
ScriptLog: 2nd pass End Trace1 : -399.622467,513.612244,166.062286
ScriptLog: 2nd pass Other : DM-StalwartXL.LevelInfo0
ScriptLog: Start Trace2 : -335.623627,510.587708,102.062286
ScriptLog: End Trace2 : -271.623627,510.563171,166.062286
ScriptLog: 2nd pass Start Trace2 : -271.623627,510.563171,166.062286
ScriptLog: 2nd pass End Trace2 : -271.622467,513.563171,166.062286
ScriptLog: 2nd pass Other : DM-StalwartXL.LevelInfo0
ScriptLog: Start Trace3 : -335.623627,510.587708,102.062286
ScriptLog: End Trace3 : -399.623627,510.612244,38.062286
ScriptLog: 2nd pass Start Trace3 : -399.623627,510.612244,38.062286
ScriptLog: 2nd pass End Trace3 : -399.622467,513.612244,38.062286
ScriptLog: 2nd pass Other : DM-StalwartXL.LevelInfo0
ScriptLog: Start Trace4 : -335.623627,510.587708,102.062286
ScriptLog: End Trace4 : -271.623627,510.563171,38.062286
ScriptLog: 2nd pass Start Trace4 : -271.623627,510.563171,38.062286
ScriptLog: 2nd pass End Trace4 : -271.622467,513.563171,38.062286
ScriptLog: 2nd pass Other : DM-StalwartXL.LevelInfo0
ScriptLog: Spawned a rocket yo
ScriptLog: Rocket hit wall here : -335.623627,510.587708,102.062286 <--difference here is Hitnormal + HitLocation, still same spot
ScriptLog: Spray Attempts : 27


The mod is grabbing a random pathnode and tracing out from it in a random 360 arc and with up to 10 degrees of upwards angle. It runs the checks for a 128X128 texture and if they all pass it spawns a rocket subclass that has my graffiti as the scorch. The rocket is spawned at the trace origin (Hitlocation + Hitnormal) and aimed with -Hitnormal. This immediately impacts it onto the wall at the right spot.

Here's the code:
Code: Select all

class GraffitiMod extends Mutator config(GraffitiMod);

var int NumNodes, NavPoint, SprayAttempts;
var bool Initialized, GraffitiAllDone;
var NavigationPoint PNodes[5001];
var config bool UseGraffiti;
var config int GraffitiNumber;

replication
{
   reliable if ( Role == ROLE_Authority )
      GraffitiNumber;
}

function PostBeginPlay()
{
   local NavigationPoint NP;

   if (Initialized)
      return;
   Initialized = True;

   SprayAttempts = 0;

   for (NP = Level.NavigationPointList; NP != None; NP = NP.NextNavigationPoint)
   {
      if (NP.IsA('Pathnode') && !NP.Region.Zone.bWaterZone)
      {
         if(NumNodes <= 5000)
         {
            PNodes[NumNodes] = NP;
            NumNodes++;
         }
      }
   }

   SetTimer(1,True);
}

simulated Function addMutator(mutator M)
{
   if(M.class==self.class)
      m.destroy();
   else super.addMutator(M);
}

function SpawnGraffiti()
{
   local int PointCount;
   local NavigationPoint NP;
   local rotator newRot;
   local vector HitLocation, HitNormal, FireDir, X, Y, Z, Origin, StartTrace, EndTrace;
   local actor HitActor, Other;
   local int i, j, N, M, SpriteX, SpriteY;
   local float yOffset, zOffset;
   local tag1 SpawnedGraffitiRocket;

   BroadcastMessage("Firing!");
   log("Firing!");
   NavPoint = int(RandRange(0,NumNodes));
   log("NavPoint :"@NavPoint);
   for (NP = Level.NavigationPointList; NP != None; NP = NP.NextNavigationPoint)
   {
      if (NP.IsA('PathNode'))
      {
         if (PointCount == NavPoint)
         {
            log("Found the nav point");
            newRot.Yaw = Rand(65535); //360 degrees around
            newRot.Pitch = Rand(1820); //from 0 to roughly 10 degrees upward angle
            newRot.Roll = 0;
            
            FireDir = vector(newRot);
            HitActor = Trace(HitLocation, HitNormal, location + FireDir * 1500, Location, false);
            log("HitActor: "@Hitactor);
            if(( HitActor == Level) && ( HitNormal.Z < 0.03 ) && ( HitNormal.Z > -0.03 ))
            {
               log("Hit the level here :"@HitLocation);
                GetAxes( rotator(-HitNormal), X, Y, Z);
               Origin = HitLocation + HitNormal;
               log("Origin location: "@Origin);

               //Pass 1  (64, 64)
               StartTrace = Origin;
               log("Start Trace1 :"@StartTrace);
               EndTrace =  Origin + Y * 64 + Z * 64;
               log("End Trace1 :"@EndTrace);
               Other = Trace(HitLocation, HitNormal, EndTrace, StartTrace, true);
               if (Other != none)
                  return;
               else
               {
                  StartTrace = Origin + Y * 64 + Z * 64;
                  log("2nd pass Start Trace1 :"@StartTrace);
                  EndTrace = StartTrace + X * 3;
                  log("2nd pass End Trace1 :"@EndTrace);
                  Other = Trace(HitLocation, HitNormal, EndTrace, StartTrace, true);
                  log("2nd pass Other :"@Other);
                  if (Other != none)
                  {

                     //Pass 2  (-64, 64)
                     StartTrace = Origin;
                     log("Start Trace2 :"@StartTrace);
                     EndTrace =  Origin + Y * -64 + Z * 64;
                     log("End Trace2 :"@EndTrace);
                     Other = Trace(HitLocation, HitNormal, EndTrace, StartTrace, true);
                     if (Other != none)
                        return;
                     else
                     {
                        StartTrace = Origin + Y * -64 + Z * 64;
                        log("2nd pass Start Trace2 :"@StartTrace);
                        EndTrace = StartTrace + X * 3;
                        log("2nd pass End Trace2 :"@EndTrace);
                        Other = Trace(HitLocation, HitNormal, EndTrace, StartTrace, true);
                        log("2nd pass Other :"@Other);
                        if (Other != none)
                        {

                           //Pass 3  (64, -64)
                           StartTrace = Origin;
                           log("Start Trace3 :"@StartTrace);
                           EndTrace =  Origin + Y * 64 + Z * -64;
                           log("End Trace3 :"@EndTrace);
                           Other = Trace(HitLocation, HitNormal, EndTrace, StartTrace, true);
                           if (Other != none)
                              return;
                           else
                           {
                              StartTrace = Origin + Y * 64 + Z * -64;
                              log("2nd pass Start Trace3 :"@StartTrace);
                              EndTrace = StartTrace + X * 3;
                              log("2nd pass End Trace3 :"@EndTrace);
                              Other = Trace(HitLocation, HitNormal, EndTrace, StartTrace, true);
                              log("2nd pass Other :"@Other);
                              if (Other != none)
                              {
                                 
                                 //Pass4  (-64, -64)
                                 StartTrace = Origin;
                                 log("Start Trace4 :"@StartTrace);
                                 EndTrace =  Origin + Y * -64 + Z * -64;
                                 log("End Trace4 :"@EndTrace);
                                 Other = Trace(HitLocation, HitNormal, EndTrace, StartTrace, true);
                                 if (Other != none)
                                    return;
                                 else
                                 {
                                    StartTrace = Origin + Y * -64 + Z * -64;
                                    log("2nd pass Start Trace4 :"@StartTrace);
                                    EndTrace = StartTrace + X * 3;
                                    log("2nd pass End Trace4 :"@EndTrace);
                                    Other = Trace(HitLocation, HitNormal, EndTrace, StartTrace, true);
                                    log("2nd pass Other :"@Other);
                                    if (Other != none)
                                    {
                                       log("Spawned a rocket yo");
                                       SpawnedGraffitiRocket = Spawn(class'tag1',,, Origin,rotator(-HitNormal));
                                    }
                                 }
                              }  else return;
                           }
                        } else return;
                     }
                  } else return;
               }
            } else return;
           } PointCount++;
      }
   }
}

simulated function Timer()
{
   local Tagz1 T;
   local int Q;
   local PathNode PN;

   if (Level.Game.bGameEnded) return;

   if(!GraffitiAllDone)
   {
      SprayAttempts +=1;
      log("Spray Attempts :"@SprayAttempts);
      if (SprayAttempts > 60) //cap number of tries to prevent runaway
         GraffitiAllDone = true;

        Q=0;
        forEach AllActors(class'Tagz1', T) //cap number of sprays for the map
        {
           if (T !=none)
              Q +=1;
           log("Q ="@Q);
         if (Q >= GraffitiNumber)
              GraffitiAllDone = true;

        }

      if(!GraffitiAllDone)
      {
           BroadcastMessage("PING!");
           log("PING");
           SpawnGraffiti();

        }
        else
        SetTimer(0, False);
     }
}

defaultproperties
{
   GraffitiAllDone=False
   UseGraffiti=true
GraffitiNumber=4
}



I broke the checks down into a linear progression so I could understand them better and see everything that's going on. I'm sure they could be done in a 'For' loop but I really want to understand each line of code and why it's doing what it's doing.

Whew. Thanks for reading so far....Mind a couple of questions? First, if you see improvements to the checks I'd very much love to hear them. Turns out it's rather hard to randomly select a proper spot. Very often the mod runs out of attempts before it finds enough candidates to place 5 graffiti. Any speed improvement would be very helpful. Secondly, I have the check running anew every second. Can I speed that up some without impacting the server? I don't really know how fast these traces are running. I still need to give time for the spawning of the graffiti but can I run these at 4 or 5 a second you think?
You maybe ought to go ahead and add /s to whatever I posted above just to be safe.
User avatar
JackGriffin
Godlike
 
Posts: 3545
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: Hack coder

Re: Need help with trace function for decal placement

Postby sektor2111 » Mon Nov 12, 2018 5:24 pm

JackGriffin wrote:First, if you see improvements to the checks I'd very much love to hear them. Turns out it's rather hard to randomly select a proper spot. Very often the mod runs out of attempts before it finds enough candidates to place 5 graffiti. Any speed improvement would be very helpful. Secondly, I have the check running anew every second. Can I speed that up some without impacting the server? I don't really know how fast these traces are running. I still need to give time for the spawning of the graffiti but can I run these at 4 or 5 a second you think?

A few thoughts not about vectors because I'm not good there... but in order of ideas:
- 5 grafitti ? Perhaps using a state code with a small pause and Re-Acquiring other 5 points for more spreading or going to 10 pieces ? In a state code with sleep you can make things to not even be noticed as smoother as it works. I don't think it's a must-have all of them in the same moment. If happens after 1-3 seconds no one gets hurt - I think - you can capture how many have spawned using some array or whatever toy for protecting the same node for being in account to not spread 2 decals in the same location;
- Speeding up server ? Move these in client - server is not appreciating decals anyway and each client might have it's own decals. Btw, I could use this "UB" code in some patch files spreading decals in "hard-coded" spots, projectiles are spawned only in client. A lot of things can be guided by client - including some decoration pawns which I spread in a SkyBox entirely visible On-Line. More things can be operated by client itself without server's participation. Everything starts in a SpawnNotify thing, you have all chances to have them smoother, server will not even blink.
There are also those deco-things where I saw a replication code to solve. My solution was to subclass them in empty child non-static classes and without RemoteRole, dropping them around completely in client - by using this way you will never be a victim of RelevantTimeout or other visual borks specific to server's replication, a decoration behind a Transparent Wall will never go vanished in Net Play if it's an authoritative part of client - server has no data to destroy so it will sit there until end of match.
User avatar
sektor2111
Godlike
 
Posts: 3554
Joined: Sun May 09, 2010 6:15 pm
Location: vect(1,1,1)

Re: Need help with trace function for decal placement

Postby JackGriffin » Mon Nov 12, 2018 6:27 pm

I spawn a very low light onto the decal once it's placed so it can be seen even in a dark corner. It's not harsh, it barely lights the texture but I use that light to check for existing graffiti in the area. When the rocket explodes it does a radius check as the final thing and if there are no more 'GraffitiLight' in the area it will spawn the decal.

Let me make sure I understand you right. Aren't the graffiti pretty much client-side already? I mean the rocket spawns them and the server sends the location to the client but that's really it. They don't expire with a lifetime setting so the server never updates them again. The load of these things occurs when the traces are running.

Edit: I should also have added this. Is there a definitive place where trace events are outlined? I'm wondering if it's worth converting some of these to fasttrace but I'm not sure since they are very short. There's not much I can find on the subject.
You maybe ought to go ahead and add /s to whatever I posted above just to be safe.
User avatar
JackGriffin
Godlike
 
Posts: 3545
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: Hack coder

Re: Need help with trace function for decal placement

Postby sektor2111 » Tue Nov 13, 2018 7:11 am

JackGriffin wrote:Aren't the graffiti pretty much client-side already? I mean the rocket spawns them and the server sends the location to the client but that's really it. They don't expire with a lifetime setting so the server never updates them again. The load of these things occurs when the traces are running.
I think client can process these traces as well, server says: Hey, client, I have a task for you. Notifier will fire something an actor (with no RemoteRole) and this actor will work itself doing traces and what has to be done - if exist a configuration will need a small replication data to be sent. If this would be my work I would do these in client because they don't have to be server-authoritative are not called Killed ScoreKill and crap from Level.Game, client doesn't have Level.Game and decals have nothing with them.

After working a few client-side things - a SnowGenerator or such, I could see that client can manage a lot of stuff - called by client itself too (particle here):
- Touch; - landing on actors and sitting there 3 seconds
- HitWall; - sit there and get vanished in 3 seconds
- Landed; - splash effect or sit there for 3 seconds
- etc.
Server will only know that exist an actor able for doing stunts but has not clue if it's snowing or not - (if it do spreads decals or not in your case), it will ignite this one (radius, density, particle size, etc. - number of decals for you) and doing nothing later, I sustain what I say because I used logs and I was tracking what happens and where - server has no task to do here, it's smoother as butter. Due to this way of attacking client, you can have stuff even in other zone than where player is, and perfectly visible in player.

Cons at me:
The problems with such stuff will not work in my patch files when is about Level.NavigationPointList - an empty Level, pathed later doesn't have such thing in clients, or paths-net goes changed (completed), all paths added in run-time belongs to server-only - and here it's not place for decals else they might work but initialized from server AFTER a few seconds...
User avatar
sektor2111
Godlike
 
Posts: 3554
Joined: Sun May 09, 2010 6:15 pm
Location: vect(1,1,1)

Next

Return to Coding, Scripting

Who is online

Users browsing this forum: No registered users and 2 guests