Announcement

Collapse
No announcement yet.

SeekingProjectiles seeking... projectiles

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

    SeekingProjectiles seeking... projectiles

    Hi all,

    I'm trying to implement Seeking projectiles that seek specific classes (initially my customized extension of the UTProj_ShockBall class) and wanted to see if anyone could offer advice on my current direction or any suggestions on a better way to go about this.

    My goal is to have the seeking projectile (extended from UTProj_SeekingRockt.uc) home-in on a slow-moving or stationary ShockBall, and orbit the projectile without colliding (turning off collision/explosion). I have already set all projectiles to bounce off static meshes so the projectiles will persist until the user calls a destroy exec function (an iterator call across AllActors calling Explode on UTProjectiles).

    Currently I have a rudimentary seeking solution working where the SeekingRocket immediately targets the most recent ShockBall fired and tracks it until it passes through the object. At that point, it usually takes on the direction from the ShockBall and no longer tries to seek, though occasionally it will sharply cut back and forth once or twice before giving up and heading out to pasture.

    In my custom OSCWeap_RocketLauncher_Content.uc, I use CanLockOnTo to set the LockedTarget:

    Code:
     simulated function bool CanLockOnTo(Actor TA)
     {
     	if(TA.class == class'OSCProj_ShockBall') {
     		`log("Locked on: "$LockedTarget$" with current: "$TA);
     		return true;
     	} else {
     		return false;
     	}
     }
    And set my custom SeekingRocket class to be fired in defaultproperties:

    SeekingRocketClass=class'OSCProj_SeekingRocket'

    So far so good.

    In my custom SeekingRocket class, I implement setSeekTarget() to choose a ShockBall to seek (brute force for now, but its working at least):

    Code:
    function setSeekTarget(){
    /** Currently tracked target - if set, projectile will seek it */
    
        local OSCProj_ShockBall P;
    
        ForEach AllActors(class'OSCProj_ShockBall',P)
        {
            if(FastTrace(P.Location,Location))
             {
                   SeekTarget = P;
             }
          }
    }

    I then call setSeekTarget() in PostBeginPlay() for the SeekingRocket.

    Does this seem like a correct way to go about modding the seeking behavior of UDK projectiles? I've been unable to find any good descriptions of how this is really implemented. I'm willing to work out the vector math required to update rocket position per tick but it seemed like this behavior might already be in the core UDK engine.

    Any help would be fantastic, thanks in advance.

    (I'll reformat the code blocks above when I figure out how )

    * EDIT - reformatted code blocks with code tag
    ================================================== =

    For more info about my project in general:

    http://forums.epicgames.com/showthre...1#post27580921

    #2
    Hi!

    In your projectile, when you seek a new target, try to use the Tick() function. Then, consider the following:

    1- Once target has been identified, move the projectile towards the target.

    2- Once it reaches to a specific range away from the target, change the behavior of the movement so that it rotates around the target and follows it.

    Comment


      #3
      Hi seenooh, thanks for your response.

      So you'd advise doing the vector calculations manually within the Tick function? Would it be too computationally expensive in UScript to do the vector math and call SetLocation on each Tick?

      I'm willing to go that route if that's the only way to go; based on the initial success of simply setting the SeekTarget on the projectile, I was under the impression (perhaps misguided) that the native seeking code could be repurposed with the correct set of defaultproperties and a correctly set SeekTarget object.

      I'll give it a look. In the meantime, if anyone has other suggestions, I'd love to hear them.

      I'm surprised I can't find more existing examples of homing or seeking projectile scripts; I've pulled some examples from UDK vehicle missile code but that seems a bit different. If there's a great example out there I've missed I'd appreciate any direction.

      thanks!

      Comment


        #4
        Originally posted by robertkhamilton View Post
        Hi seenooh, thanks for your response.

        So you'd advise doing the vector calculations manually within the Tick function? Would it be too computationally expensive in UScript to do the vector math and call SetLocation on each Tick?

        I'm willing to go that route if that's the only way to go; based on the initial success of simply setting the SeekTarget on the projectile, I was under the impression (perhaps misguided) that the native seeking code could be repurposed with the correct set of defaultproperties and a correctly set SeekTarget object.

        I'll give it a look. In the meantime, if anyone has other suggestions, I'd love to hear them.

        I'm surprised I can't find more existing examples of homing or seeking projectile scripts; I've pulled some examples from UDK vehicle missile code but that seems a bit different. If there's a great example out there I've missed I'd appreciate any direction.

        thanks!

        You welcome, glad that I could be of help.

        I was implementing something which needs this seeking behavior. During the past week I was developing a boomerang weapon, once it hits the target it should seek the player and become "returned".

        I tried many things, but ended up doing it manually in the tick function. Sometimes, the default implementation cannot help you. Example: I was developing another weapon which shoots projectiles that reflect when hitting objects. Once it reaches some distance without hitting anything, I'm setting Physics = PHYS_Falling so that it starts falling, however it behaves in a wrong manner... the falling direction is wrong, it suddenly changes to the opposite direction... So basically, the implementation depends on the initial velocity only and doesn't assume that it might change or something. So I had to do it manually.

        So I believe your case is similar to mine.

        EDIT: And as for performance, I already have two weapons doing similar stuff in the tick(), and no noticable performance hits. Give it a shot.

        Comment


          #5
          Great. Thanks again.

          So you're using something like a Pursuit Curve (i.e. http://mathworld.wolfram.com/PursuitCurve.html)?

          Time to dust off my brain

          Comment


            #6
            I think you might be able to SetBase to the projectile that you're seeking, once it is attached to it, and then it'll remain linked to it. I'm not sure if you'll be able to rotate around the item once it's attached though. Probably using SetRelativeLocation, I think is the function to adjust it's location in relation to it's base. You might be able to even set a PrePivot on it, and then start it PHYS_Rotating, or something. This isn't something I've ever tried to do.

            Worst case, rather than doing SetLocation, I'd probably adjust the Velocity on it - SetLocation or Move on an actor with collision is rather costly.

            Comment


              #7
              Or you know what? Make a trick =p ... Now the scenario is that you want the enemie's projectile to have something to rotate around it when you shoot it.

              Why don't you make it so that when the enemie shoots, the weapon spawns two projectiles, the regular one, and the one that's rotating around it, only that the latter has bHidden = true... Now when you hit that projectile, all you have to do is SetHidden(false) ! Easier I believe?

              Comment


                #8
                What is it that you're ultimately trying to achieve?

                Comment


                  #9
                  Hah, that won't work for me seenooh, thanks though.

                  Ultimately I'll be firing off slow moving ShockBalls which I'll then control their position using an iPad. The Seeking Projectiles will then be fired and will track the ShockBalls. They should pass through the ShockBalls but will collide with a custom KActor or InterpActor class of mine which sends messages which will drive sound from an external engine.

                  This will let me control basically swarms of projectiles by moving the ShockBalls by hand/iPad, giving me a general control of how they interact/bounce off of parts of the environment, all of which generates sound.

                  The homing should work something like this old quake 3 demo video of mine from an earlier project:

                  http://www.youtube.com/watch?v=WRNDf...eature=related

                  I'm getting closer, but my math is rusty. I'm currently using a method that's called on each Tick of the SeekingRocket; the math is off but I'm getting closer, projectiles track the ShockBall's with a nice arc but then either get stuck into it and stay stuck to it, or move outside the radius that would pull them into the ShockBall. Currently, it's looking something like this (Apologies for the sad equations):

                  Code:
                  function calcPursuit()
                  {
                          local float angle, lambda;
                          local float MaxAngleDelta;
                  	
                  	// Dot product of 2 vectors is the cosine of the angle between them. Compare angle between projectiles and limit to MaxAngle value; add .000001 to offset possible divide by zero
                  	angle = acos(Normal(OSCSeekTarget.Location) dot Normal(Location)) + 0.00001; 	
                  	MaxAngleDelta = 0.0005;
                  	
                  	if (angle <= MaxAngleDelta || VSize(OSCSeekTarget.Location - Location) <= 50.0)
                  	{
                  		Velocity = VSize(Velocity) * Normal(OSCSeekTarget.Location - Location);
                  	}
                      else
                      {
                         lambda = MaxAngleDelta / (angle - MaxAngleDelta);
                         Velocity = Normal(((Normal(Vector(Rotation)) * VSize(OSCSeekTarget.Location - Location) + Location) + lambda * OSCSeekTarget.Location) * (1.0 / (1.0 + lambda)) - Location) * VSize(Velocity);
                      }
                      //Speed = VSize(Velocity);
                      //SetRotation (rotator(Velocity));
                  }
                  * EDIT - updated code tags

                  Comment


                    #10
                    In the projectile class:

                    Code:
                    var vector vTargetLoc; //the target we're seeking
                    
                    simulated event Tick(float deltaTime)
                    {
                    	local Rotator  rNewRotation;
                    	local Vector   vNewLocation, vCenter; 
                    	local float      fMaxRange, fDistanceToTarget; 
                                 local Vector   Vector vProjHitLoc; //added this for readbility
                    
                    	fMaxRange = GetTheMaxRange(); 
                    	fDistanceToTarget = VSize(vTargetLoc - self.Location);
                    
                    	if (fDistanceToTarget <= fMaxRange )
                    	{
                    		ProjHitLoc = self.Location;		
                    
                    		rNewRotation = Rotation; 
                    
                    		rNewRotation.Yaw = 0;
                    		rNewRotation.Pitch = 0; 
                    		rNewRotation.Roll += 9000 * deltaTime; 
                    
                    		vNewLocation = vTargetLoc + Normal(Vector(rNewRotation)) * fDistanceToTarget;
                    
                    		SetLocation(vNewLocation); 
                    		SetRotation(rNewRotation);
                    
                    	}
                    	
                    }
                    I haven't tested this but it can help...

                    Comment


                      #11
                      I think Seenoh and Blade are correct, I've also done a boomerang weapon, and I frankly did it pretty much like Seenoh did it. Just keep updating the target location via Tick and applying force to get it there. As Seenoh said, it never caused any noticable performance issue when I tried it. I think the idea of scaring people off of being Tick happy is that 1) you should TRY to think of a way around it and 2) if you really do go nuts with all your custom classes Ticking, it might actually be a problem.

                      The only way to avoid Tick that I can think of would be similar to what Blade said, or a hybrid where you call Tick until it's close enough, then use Blade's suggestion. Don't forget bProjTarget while you're at it

                      Comment


                        #12
                        dan i think most people avoid tick because a tick is different on different cpu's.

                        a tick goes as fast as it can, thats the whole point of the deltatime so you can sync things in tick to go as fast as a deltatime pass.

                        if you remember the speedhack stuff, thats close to what would happen.

                        your code might run fine on your pc but if someone has a faster or slower pc and the tick was different, this can cause issues.


                        (feel free to interject if im mistaken tho guys!)

                        Comment


                          #13
                          well, you should be able to account for the differences in tick times, which should be not noticeable except perhaps in extreme situations. I prefer to do as much as possible using native, but you're right, sometimes it's just not possible, and there's not much else you can do.

                          Comment


                            #14
                            Originally posted by TOP-Proto View Post
                            dan i think most people avoid tick because a tick is different on different cpu's.

                            a tick goes as fast as it can, thats the whole point of the deltatime so you can sync things in tick to go as fast as a deltatime pass.

                            if you remember the speedhack stuff, thats close to what would happen.

                            your code might run fine on your pc but if someone has a faster or slower pc and the tick was different, this can cause issues.


                            (feel free to interject if im mistaken tho guys!)
                            I don't disagree, I was just pointing out that Tick is often the "easy" way out, and I think its a good idea to "try" to figure out a better solution (like Blade's).

                            Though my understanding is that DeltaTime (and things like TimeFromLastTick) are used to account for the differences in Ticks. I ran into the Tick differences with my grapple, where initially the laptop and desktop were returning a different ropelength (not good). Frankly though, Tick is used everywhere in the code I look through, on some pretty gamplay sensitive stuff. They just use corrective methods (and so do I) to equalize the differences, but yes, I'm sure in extreme circumstances in the right scenarios it could go crazy

                            Comment


                              #15
                              yes tick is fine to use when needed (in my opinion), but i think theres a lower limit on how fast you should call your code... its probably 100ms which is 1/10th a second. Anything under that is probably going to start taxing your users CPU more heavily.

                              That and bear in mind that script called code is slower than native code anyway.


                              Anyone who uses a tick without checks should have some **** good reasons for doing so. I dont think theres any real valid reasons for "call this code as fast as possible" as how will you ever maintain synchronicity across clients.

                              obviously correct use of tick is absolutely vital for networked games to keep them in sync. bear in mind that your gonna get latency anyway your probably looking at pings of 50 - 100ms on a server so thats like 10 - 20 tick updates a second.

                              Comment

                              Working...
                              X