Search Unity

katt's scripting tests

Discussion in 'Scripting' started by kattkieru, Oct 8, 2007.

  1. kattkieru

    kattkieru

    Joined:
    Jan 2, 2006
    Posts:
    130
    Hey all,

    First, thanks again to all the folks who helped me out in my noob thread. Here's the results of my second weekend with Unity:

    http://ministryofdoom.org/cloud/unity/shiptest2.html

    Waypoints FTW! There're no controls, and it just loops around the "city". I did it by making two rigid bodies, one that follows the waypoints quite closely (target) and one that follows the target (follower). This gives the illusion of bezier path following without having to do bezier math (which I find myself totally unable to comprehend). (Code package at the bottom of this post.)

    I'm using rigid bodies for this, but I'm worried -- when I add combat later will this solution hold up? How are other people solving "on rails" combat? I've seen a few projects searching through the forums but little code. (I might be searching with the wrong words.) I want it to eventually feel like StarFox 64 and then branch out from there. Currently my idea is to encase the player in an invisible box that follows the waypoints and to somehow dampen thrust when you near the edges of the box (thinking about using raycasting for this), making it look like you're still thrusting while actually keeping you on track, but I'm having trouble getting it all together. That's probably next weekend's trick. ^_^

    Also, could someone explain how to slerp between two angles in a way that a three year old could understand it? That's what I tried first and got nowhere.

    And in case it helps anyone, here's my project. There's waypoint code, waypoint followers, and a lot of Gizmo drawing:

    http://ministryofdoom.org/cloud/unity/shiptest2.zip
     
  2. skyhawk

    skyhawk

    Joined:
    Jun 13, 2005
    Posts:
    49
    here's how I do it in my current project (a shmup):

    * I have a way points which are just transforms with scripts with variables attached (info like hold time, transfer time, blah blah). All are called PathingNode# (just to help in my mind lay them out and find them

    * I have a transform with a pathingscript on it that points to current node, next node, and lerps, slerps, and burps between them. This is the GamePath. This is also what most objects's transform parent if I want them to move with my scene.

    * My camera system targets the gamepath object and follows it.
     
  3. kattkieru

    kattkieru

    Joined:
    Jan 2, 2006
    Posts:
    130
    So your pathingnode isn't a rigidbody, then? You just use linear translation from point to point?
     
  4. kattkieru

    kattkieru

    Joined:
    Jan 2, 2006
    Posts:
    130
    A quick editor thing: I wanted a way to simply extend waypoint paths, so this is a function that creates a new waypoint if none are selected, or extends a current waypoint path. It's not all that smart but works well for my needs.

    Code (csharp):
    1.  
    2.  
    3. class EditorWayPoint extends ScriptableObject
    4. {  
    5.     static function CountWayPoints() : int {
    6.         var count = 0;
    7.         var wparray = FindObjectsOfType(GameObject);
    8.         for (gob in wparray) {
    9.             if (gob.GetComponent("cwWayPoint"))
    10.                 count++;
    11.         }
    12.         return count;
    13.     }
    14.  
    15.     @MenuItem ("katt/WayPoints/Create WayPoint")
    16.    
    17.     static function CreateWayPoint()
    18.     {
    19.         var numPoints = CountWayPoints();
    20.         var ob = GameObject("WayPoint" + numPoints);
    21.         ob.AddComponent("cwWayPoint");
    22.         if (Selection.transforms.length) {
    23.             var wp = Selection.activeGameObject.GetComponent("cwWayPoint");
    24.             if (wp) {
    25.                 wp.target = ob;
    26.                 ob.transform.position = Selection.activeGameObject.transform.position;
    27.             }
    28.         }
    29.        
    30.         Selection.activeGameObject = ob;
    31.     }
    32.  
    33. }
    34.  
    35.  
    Course, the cwWayPoint class is in the file linked above.
     
  5. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
    This is very cool. Any plans to add some way to vary ship speed? Perhaps have it randomly accelerate or decelerate, or better yet, have it slow as it approaches a waypoint, then accelerate after it turns? How will you handle "banking" the ship?
     
  6. skyhawk

    skyhawk

    Joined:
    Jun 13, 2005
    Posts:
    49
    correct
     
  7. kattkieru

    kattkieru

    Joined:
    Jan 2, 2006
    Posts:
    130
    edit: got bezier line drawing working, script changed.

    @BigKahuna:

    Varying ship speed is pretty easy... just increase the thrust over time. I was thinking of doing something like that, possibly, by including new thrust speeds inside the waypoints. I figure I can dump a lot of data inside each waypoint and have the Follower ramp up or down to the new speed. I have a similar idea for the up vector (so that I can have the camera rotate along the path a certain way, like into ground holes or straight up without flipping out), but it's not baked yet.

    What is baked, though, is bezier waypoints!

    Code (csharp):
    1.  
    2. var turnTime : int = 40;
    3. var nextDist : float = 2.5;
    4. static var kLineOfSightCapsuleRadius = 0.25;
    5. var target : GameObject;
    6. var target2 : GameObject;
    7.  
    8. var size : float = 0.5;
    9. var drawCurve : boolean = true;
    10. var drawHandles : boolean = true;
    11. var drawAsLine : boolean = true;
    12. var curveType : int = 4;        // 4 = cubic bezier, 3 = quadratic
    13. var curveSegments : float = 10.0;   // how smooth the curve should be
    14. var curveDrawType : int = 1;    // 1 = spheres, 2 = line
    15. var curveSphereSize : float = 1.0;
    16.  
    17. // Draw the waypoint pickable gizmo
    18. function OnDrawGizmos () {
    19.     // Draw lines to the targets if they exist
    20.     ODG_LineToTarget(target);
    21.     ODG_LineToTarget(target2);
    22.    
    23.     Gizmos.color = Color.green;
    24.     Gizmos.DrawWireSphere(transform.position, size);
    25.     Gizmos.DrawIcon (transform.position, "Waypoint.tif");
    26.     if (target) {
    27.         // draw bezier curve
    28.         if (drawCurve) {
    29.             var distance : float = Vector3.Distance(target.transform.position, transform.position);
    30.             var qdist : float = distance / 4.0;
    31.    
    32.             var p1 : Vector3 = transform.TransformPoint(0, 0, qdist);
    33.             var p2 : Vector3 = target.transform.TransformPoint(0, 0, -qdist);
    34.  
    35.             if (drawHandles) {
    36.                 //debug: draw bezier "handles"
    37.                 Gizmos.color = Color.red;
    38.                 Gizmos.DrawLine(transform.position, p1);
    39.                 Gizmos.color = Color.blue;
    40.                 Gizmos.DrawLine(p2, target.transform.position);
    41.                 Gizmos.color = Color.yellow;
    42.                 Gizmos.DrawSphere(p1, curveSphereSize);
    43.                 Gizmos.DrawSphere(p2, curveSphereSize);
    44.             }
    45.  
    46.             // draw the bezier based on the distance and the number of segments
    47.             // does the rounding matter?
    48.             var jumpdist : float = 1.0 / curveSegments;
    49.  
    50.             // #!FIXME: make it draw lines too
    51.             var lineStart : Vector3 = transform.position;
    52.             var lineEnd : Vector3;
    53.            
    54.             if (!drawAsLine)
    55.                 Gizmos.color = Color.green;                                    
    56.             else
    57.                 Gizmos.color = Color.red;
    58.  
    59.             for (var i : int = 1; i < curveSegments; i++) {
    60.                 lineEnd = PointOnBezier4(transform.position, p1, p2,
    61.                                     target.transform.position, jumpdist * i);
    62.                 if (!drawAsLine)
    63.                     Gizmos.DrawSphere(lineEnd, curveSphereSize);
    64.                 else {
    65.                     Gizmos.DrawLine(lineStart, lineEnd);
    66.                     lineStart = lineEnd;
    67.                 }
    68.             }
    69.         }
    70.     }
    71. }
    72.  
    73. function PointOnBezier4(p1 : Vector3, p2 : Vector3, p3 : Vector3, p4 : Vector3, t : float) : Vector3 {
    74.     var q1 : Vector3 = Vector3.Lerp(p1, p2, t);
    75.     var q2 : Vector3 = Vector3.Lerp(p2, p3, t);
    76.     var q3 : Vector3 = Vector3.Lerp(p3, p4, t);
    77.     var r1 : Vector3 = Vector3.Lerp(q1, q2, t);
    78.     var r2 : Vector3 = Vector3.Lerp(q2, q3, t);
    79.     var r3 : Vector3 = Vector3.Lerp(r1, r2, t);
    80.  
    81.     return r3;
    82. }
    83.  
    84. // Draw the waypoint lines only when you select one of the waypoints
    85. function OnDrawGizmosSelected () {
    86.     Gizmos.color = Color.yellow;
    87.     Gizmos.DrawWireSphere(transform.position, size);
    88.     Gizmos.DrawIcon (transform.position, "Waypoint.tif");
    89.    
    90.     // draw "bezier" lines
    91. }
    92.  
    93. function ODG_LineToTarget(ntarget) {
    94.         // for target 1
    95.     if (ntarget) {
    96.         if (Physics.Linecast(transform.position, ntarget.transform.position))
    97.         {
    98.             Gizmos.color = Color.red;
    99.             Gizmos.DrawLine (transform.position, ntarget.transform.position);
    100.         }
    101.         else
    102.         {
    103.             Gizmos.color = Color.green;
    104.             Gizmos.DrawLine (transform.position, ntarget.transform.position);
    105.         }
    106.     }
    107. }
    108.  
    109.  
    Essentially, a waypoint that has a waypoint for its target will use the Gizmos to draw the path. I'm cheating a lot -- I couldn't think of a simple way to seam together two four-point bezier curve, so I'm kind of making each waypoint like a bezier point with handles. The handles lie along the Z axis. Red points forwards, and blue points backwards.

    Hopefully it'll make sense if you try it out on some empties. Here's a quick screenshot. Next up: bezier pathing in the Follower!

    If you want a way to add WayPoints easily, check out the script above. Hope someone finds the above useful. ^_^
     

    Attached Files:

  8. kattkieru

    kattkieru

    Joined:
    Jan 2, 2006
    Posts:
    130
    New noob question: What's the quickest way to determine the screen position of an object's transform? I searched the forum and the docs but I must be using the wrong words because I can't find anything on it.

    Thanks in advance!
     
  9. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Sounds like you want WorldToViewportPoint.

    --Eric
     
  10. kattkieru

    kattkieru

    Joined:
    Jan 2, 2006
    Posts:
    130
    Brilliant! Thanks mate. I knew there had to be a function.
     
  11. kattkieru

    kattkieru

    Joined:
    Jan 2, 2006
    Posts:
    130
    Here's what I came up with. It seems to work... Right now I've got an empty parented to the camera so that I can get a working vector. I think Transform.forward works very differently from how I envision it working?

    Anyway, is what I have the best way to be doing this -- keeping a texture on-screen -- or is there a simpler / better way? This script is applied to an in-world empty that then moves a 64x64 GUI texture based on the camera and the camera's target. The reason I'm using angles is that the objects seem to come up once every 180 degrees.

    Code (csharp):
    1.  
    2. var innerTexture : GUITexture;
    3. var outerTexture: GUITexture;
    4. var cam : Camera;
    5. var camTarget : GameObject;
    6. var debugGUI : GUIText;
    7.  
    8. var innerSize : float = 1.0;
    9. var outerSize : float = 1.0;
    10.  
    11. function Update () {
    12.    
    13.     var theVec : Vector3 = camTarget.transform.position - cam.transform.position;
    14.     var angle = Vector3.Angle(theVec, transform.position - cam.transform.position);
    15.     if (angle < 90) {
    16.         var pos = cam.WorldToScreenPoint(transform.position);       debugGUI.text = "(" + pos.x + ", " + pos.y + ") : Angle " + angle;
    17.         innerTexture.pixelInset = Rect(pos.x - 32, pos.y - 32, 64, 64);
    18.         innerTexture.color.a = 255;
    19.     }
    20.  
    21.     else {
    22.         debugGUI.text = "Offscreen - Angle is " + angle;
    23.         innerTexture.color.a = 0;
    24.     }
    25. }
    26.  
     
  12. nickavv

    nickavv

    Joined:
    Aug 2, 2006
    Posts:
    1,801
    Your waypoint system looks awesome! I might just have to try it out. :D
     
  13. kattkieru

    kattkieru

    Joined:
    Jan 2, 2006
    Posts:
    130
    I've made some progress. A lot of progress, actually, although from this next test you probably won't think so:

    REMOVED LINK

    This may not seem to exciting, but it's using a fully-functional version of my bezier waypoints. (Please ignore the crappiness of the animation -- it was just for testing purposes.) Here's a shot of that:



    Essentially the bird is on an infinite loop that's smoothed out. There's still a kink or two to work through, but I think it's working well enough for the next phase of what I want to get going. The waypoints are finally working well enough that I can start on some Really Fun Stuff™.
     
  14. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
    That's weird, I just tried your link and it loaded most of the way then I got a "Failed to update webplayer" error? Anyone else?
     
  15. kattkieru

    kattkieru

    Joined:
    Jan 2, 2006
    Posts:
    130
    Damn you're fast. ^_^ It works fine on my end... I can generate a standalone if folks want, but it's really just a bird flying in a circle.
     
  16. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Your web player was made with the leopard build. Please do not post web players that are made with non-official Unity builds.
     
  17. kattkieru

    kattkieru

    Joined:
    Jan 2, 2006
    Posts:
    130
    I apologize! I didn't know there'd be a difference -- figured the VM or whatever runs things wouldn't have a problem.

    I've rebuilt the example using 2.0.0f6. That's the official release, I hope; a look inside the HTML shows that the user is redirected to grab the beta web player?

    Again, sorry. I have the beta in another folder, and I just ran this on my PC, so it should work now.

    http://ministryofdoom.org/cloud/unity/mushroom-house.html

    bigkahuna, does it work for you now? You'll probably have to reload the page.
     
  18. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
    Ahhh... now that works much better!