Results 1 to 5 of 5

Hybrid View

  1. #1
    MSgt. Shooter Person
    Join Date
    Sep 2010
    Location
    Bolton, UK
    Posts
    46

    Default Attaching Train to rails using splines - help desperately needed!

    Hey guys,

    Im having loads of trouble here, hopefully someone can help. Ive got a spline class set up to allow a default pawn to move along the spline,however when I spawn him into a vehicle using Kismet (even when using Script) the vehicle can move away from the tracks even though its still connected to the spline whereas the spawn stays locked in. Does anyone know how I would adapt this class for a vehicle? I've been trying for over a month now with no success.

    PlayerControllerClass:

    Code:
    class TrainPlayerController extends GamePlayerController;
    
    var         SplineConstraint          Constraint;   //Constraint 
    
    struct sSplinePath
    {
    	var SplineActor StartAnchor;
    	var SplineActor EndAnchor;
    	var array<SplineActor> Path;
    
    	var SplineActor NearAnchorLow;
    	var SplineActor NearAnchorHigh;
    	var float RecentPosition;
    	var float RespectivePosition;
    	var Vector RecentLocation;
    };
    
    simulated event PostBeginPlay()
    {
    	super.PostBeginPlay();
    
    	//Setup our Constraint
    	Constraint = new class'SplineConstraint';
    	Constraint.Initialize(WorldInfo);
    	//
    	TrainInfo(WorldInfo.Game).RestartPlayer(self);
    }
    
    event PlayerTick( float DeltaTime )
    {
    	if(Constraint.Pawn == none)
    		Constraint.SetConstraint(Pawn);
    
    	super.PlayerTick(DeltaTime);
    	Constraint.Update(DeltaTime);
    }
    
    DefaultProperties
    {
    
    }
    Spline Constraint:
    Code:
    class SplineConstraint extends Object;
    
    var         Pawn             Pawn;                  //Pawn to Constrain to the Spline
    var         array<SplineActor> SplineCache;           //Cache of our Current SplineActors         
    var         Vector             StartPosition;         //Pawn's Start location on the Path
    var         float              Leeway;                //if the Pawn is farther than this amount the constraint will Lerp it back
    var         float              LerpSpeed;             //How fast the Pawn gets Lerp'd into position
    
    var         bool               bEnableDebug;          //Is Debugging enabled for the SplineConstraint
    
    exec function ShowConstraint()
    {
    	bEnableDebug = !bEnableDebug;
    
    	if(bEnableDebug)
    	{
    		`log("Show Constraints Enabled");
    	}
    	else
    	{
    		`log("Show Constraints Disabled");
    	}
    }
    
    /**
     * Initializes the class and finds the SplineActors
     * @param WorldInfo
     */
    function Initialize(WorldInfo WorldInfo)
    {
    	local SplineActor Current;
    
    	//Add Our splines to our Cache
    	foreach WorldInfo.DynamicActors( class'SplineActor', Current)
    	{
    		SplineCache.AddItem( Current );
    
    		Current.nextOrdered = Current.GetBestConnectionInDirection(vect(0,1,0));
    
    		if(Current.nextOrdered != none)
    		{
    			Current.nextOrdered.prevOrdered = Current;
    		}
    	}
    }
    
    /**
     * Set the Pawn for Constraint and Initialize Constraint
     */
    function SetConstraint(Pawn PawnToConstrain)
    {
    	Pawn = PawnToConstrain;
    	Initialize(Pawn.WorldInfo);
    }
    
    /**
     * Updates and Enforces the Constraint
     */
    function Update(float DeltaTime)
    {
    	local SplineActor   Spline;                  //Used to iterate through our SplineCache
    	local SplineActor   CurrentSplineActor;      //Current SplineActor We are Focused on
    	local SplineActor   PrevSplineActor;         //Previous SplineActor from CurrentSplineActor
    	local SplineActor   NextSplineActor;         //Next SplineActor from CurrentSplineActor
    	local Vector        RequiredLocation;        //Position on the spline we should be constrained to
    	local Vector        Direction;               //Direction we should be facing.  Heading Vector.  using Rotator(Direction)
    	local float         BestDistance;            //Used to find the closest SplineActor
    	local float         Distance;                //Distance on the Spline to find a Location
    	local float         DotProduct;              //Used to find which side of the CurrentSplineActor we are on.
    
    	//Temp Debug Value
    	local float         Z;
    
    	//Set to a High Number
    	BestDistance = 10000;
    
    	//Find the closest SplineActor that has a Previous and Next Ordered SplineActor
    	foreach SplineCache( Spline )
    	{
    		if(VSize( Pawn.Location - Spline.Location ) < BestDistance)
    		{
    			// If this Spline doesn't have a PrevOrdered or NextOrdered then skip it.
    			// Our CurrentSplineActor needs to be one that has a Prev and Next Ordered SplineActor
    			if(Spline.prevOrdered == none || Spline.nextOrdered == none)
    				continue;
    
    			//Set our CurrentSplineActor
    			CurrentSplineActor = Spline;
    
    			//Update our BestDistance to this Spline and then check for a closer SplineActor
    			BestDistance = VSize( Pawn.Location - Spline.Location);
    		}
    	}
    
    	//Don't continue if we don't have a CurrentSplineActor
    	if(CurrentSplineActor == none) 
    		return;
    
    	NextSplineActor = CurrentSplineActor.nextOrdered;
    	PrevSplineActor = CurrentSplineActor.prevOrdered;
    
    	//Need a Previous and Next SplineActor for the Constraint to Work.
    	//Check here just in case
    	if( NextSplineActor == none || PrevSplineActor == none)
    		return;
    
    	//Set our starting location.
    	//Playerstart should be close to this in the Map.
    	if(StartPosition == vect(0,0,0))
    	{
    		StartPosition = CurrentSplineActor.prevOrdered.Location;  //Generally the start pos will be on a Prev SplineActor
    		Pawn.SetLocation(StartPosition);  
    	}
    	
    	//Find out which side of the CurrentSplineActor we are on for our positon Calculations.
    	DotProduct = Normal(Pawn.Location - CurrentSplineActor.Location) dot Normal(CurrentSplineActor.Location - NextSplineActor.Location);
    
    	//If the DotProduct is Less than 0 than we are in between the Current and Next SplineActors
    	//If the DotProduct is Greater than 0 than we are in between the Previous and Current SplineActors
    	if(DotProduct < 0)
    	{
    		//Find our 2D distance from Pawn.Location to Our CurrentSplineActor.Location
    		Distance = VSize2D(Pawn.Location - CurrentSplineActor.Location);
    
    		//Use Distance to find the required Location on the Spline
    		RequiredLocation = CurrentSplineActor.FindSplineComponentTo(NextSplineActor).GetLocationAtDistanceAlongSpline(Distance);
    
    		//Find our Heading so We can face our Pawn this way.  Not setup to go both directions yet.
    		Direction = Normal(CurrentSplineActor.FindSplineComponentTo(NextSplineActor).GetTangentAtDistanceAlongSpline(Distance));
    	}
    	else
    	{
    		//Find our 2D distance from Pawn.Location to Our PrevSplineActor.Location
    		Distance = VSize2D(Pawn.Location - PrevSplineActor.Location);
    
    		//Use Distance to find the required Location on the Spline
    		RequiredLocation = PrevSplineActor.FindSplineComponentTo(CurrentSplineActor).GetLocationAtDistanceAlongSpline(Distance);
    
    		//Find our Heading so We can face our Pawn this way.  Not setup to go both directions yet.
    		Direction = Normal(PrevSplineActor.FindSplineComponentTo(CurrentSplineActor).GetTangentAtDistanceAlongSpline(Distance));
    	}
    
    	//used for Debug
    	Z = RequiredLocation.Z;
    
    	//Set the RequiredLocation Z to the Pawn.Location.Z Since we are only Constraining X and Y
    	RequiredLocation.Z = Pawn.Location.Z;
    
    	//Enforce our Constraint
    	if(VSize2D(Pawn.Location - RequiredLocation) > Leeway)
    	{
    		//use Lerp
    		RequiredLocation.X = Lerp(Pawn.Location.X, RequiredLocation.X, LerpSpeed);
    		RequiredLocation.Y = Lerp(Pawn.Location.Y, RequiredLocation.Y, LerpSpeed);
    
    		//Set Location
    		Pawn.SetLocation(RequiredLocation);
    	}
    
    	//Face our Pawn to the the direction the Spline is faceing
    	//Needs to be modified to go both directions and dependent on the mouse cursor position.
    	Pawn.FaceRotation(Rotator(Direction), DeltaTime);
    	
    	//Check if we should show Debug
    	if(bEnableDebug)
    	{
    		//Draw a line from Pawn.Location to NextSplineActor.Location
    		Pawn.DrawDebugLine(Pawn.Location, NextSplineActor.Location, 255,0,0, false);
    
    		//Draw a line from Pawn.Location to CurrentSplineActor.Location
    		Pawn.DrawDebugLine(Pawn.Location, CurrentSplineActor.Location, 0,255,0, false);
    
    		//Draw a line from Pawn.Location to PrevSplineActor.Location
    		Pawn.DrawDebugLine(Pawn.Location, PrevSplineActor.Location, 255, 0, 0, false);
    
    		RequiredLocation.Z = Z;
    		//Draw a line from Pawn.Location to RequiredLocation
    		Pawn.DrawDebugLine(Pawn.Location, RequiredLocation, 0, 0, 255, false);
    
    		//Draw Boxes around the SplineActors to show their Location
    		foreach SplineCache( Spline )
    		{
    			Pawn.DrawDebugBox(Spline.Location, vect(10,10,10), 255, 255, 0, false);
    		}
    	}
    }
    
    DefaultProperties
    {
    	bEnableDebug = true
    	Leeway = 10
    	LerpSpeed = 0.01
    
    }
    Theres no code in my Pawn or Gameinfo class affecting the Spline either.

    Any ideas please? Help would be greatly appreciated!

  2. #2
    Iron Guard
    Join Date
    Sep 2010
    Location
    Slovakia
    Posts
    588

    Exclamation

    Sorry for bumping but i want post here my working code for other users (i think that it isn't what you are searching). I created this today. Its class of actor that is "attached to spline" or constrainted to move along it. If u want change speed of move, direction or starting location use these variables: Speed, StartingSplineActor, Direction of move ( you can assign it in actors properties in editor). It's ready for copy&paste. Everything what should u do is add mesh in def properties.



    I created this really simple code:

    Code:
    class Train extends Actor placeable;
    
    var array<SplineActor> SplineCache;             //List of all SplineActors
    var float              Distance;                //Distance on the Spline to find a Location
    var() float              Speed;                 // Speed of train - you can assign it in editor
    var SplineActor        CurrentSplineActor;   
    var() SplineActor      StartingSplineActor;       // Position where will our train start - you can assign it in editor
    
    enum ReverserDirection  // Directions of move along spline
    {
            RD_Forward,
            RD_Backward
    };
    var() ReverserDirection ReverserDir; // You can assign variable in editor
    
    function PostBeginPlay()
    {
            super.PostBeginPlay();
            InitializeSplineActors();       // Create list of all SplineActors
    }
    
    function InitializeSplineActors()
    {
    	local SplineActor Current;
    
    	foreach AllActors( class'SplineActor', Current)
    	{
    		SplineCache.AddItem( Current );
    		Current.nextOrdered = Current.GetBestConnectionInDirection(vect(0,1,0)); // Assign next spline actor
    		if(Current.nextOrdered != none)          
    		{
    			Current.nextOrdered.prevOrdered = Current; // Assign previous spline actor to prevordered var
    		}
    	}
    }
    
    function Tick(float DeltaTime)    
    {
    	local Vector        RequiredLocation;        //Position on the spline we should be constrained to
    	local Vector        Direction;               //Direction we should be facing - rotation.
    	local float         MaxDistance;           // lenght of spline component
    	local Rotator       InvertedRotation;    // Used for Backward rotation change
    
            super.Tick(DeltaTime);
           
            if(CurrentSplineActor==none)
            {
            CurrentSplineActor=StartingSplineActor; // Set our starting location as location of StartingSplineActor
            }
    
            MaxDistance = CurrentSplineActor.FindSplineComponentTo(CurrentSplineActor.nextOrdered).GetSplineLength();
            //Assigning distance between CurrentSplineActor and next spline actor
            If(ReverserDir == RD_Forward && Speed != 0) 
            {
                    If((MaxDistance-Distance) > Speed) 
                    {
                            Distance += Speed;  // Normal move
                    }
                    else
                    {
                            Distance = Speed - (MaxDistance-Distance); // ! MaxDistance-Distance < Speed
                            CurrentSplineActor = CurrentSplineActor.nextOrdered; // Setting next actor as current spline //actor
                    }
                    RequiredLocation = CurrentSplineActor.FindSplineComponentTo(CurrentSplineActor.NextOrdered).GetLocationAtDistanceAlongSpline(Distance); // Changing our distance along spline to vector
                    Direction = Normal(CurrentSplineActor.FindSplineComponentTo(CurrentSplineActor.NextOrdered).GetTangentAtDistanceAlongSpline(Distance)); // Changing our distance along spline to direction vector and converting it to unit vector
                   	
                    SetRotation(Rotator(Direction));
                   	SetLocation(RequiredLocation);
            }
            else if(ReverserDir == RD_Backward && Speed != 0)  // Inverted Move
            {
            	If(Distance > Speed)
                    {
                            Distance -= Speed; 
                    }
                    else
                    {
                            MaxDistance = CurrentSplineActor.prevOrdered.FindSplineComponentTo(CurrentSplineActor).GetSplineLength();
                            Distance = MaxDistance - (Speed - Distance);
                            CurrentSplineActor = CurrentSplineActor.prevOrdered;
                    }
    
                    RequiredLocation = CurrentSplineActor.FindSplineComponentTo(CurrentSplineActor.NextOrdered).GetLocationAtDistanceAlongSpline(Distance);           `log("RequiredLocation"@RequiredLocation);
                    Direction = Normal(CurrentSplineActor.FindSplineComponentTo(CurrentSplineActor.NextOrdered).GetTangentAtDistanceAlongSpline(Distance));
    
                    InvertedRotation = Rotator(Direction);
                   	InvertedRotation.Yaw += 32768;
                    
                    SetRotation(InvertedRotation);
                    SetLocation(RequiredLocation);
            }
    }
    
    defaultproperties
    {
    // Put your mesh code here
    }
    Last edited by nonder; 01-01-2012 at 01:30 PM.
    Czech and Slovak UDK site - www.udk-site.net-core.eu
    Space Shock project on STEAM GREENLIGHT

  3. #3
    MSgt. Shooter Person
    Join Date
    Sep 2010
    Posts
    138

    Default

    Ive noticed that this required you to enter a speed value in order for the vehicle to move along the spline. Is there anyway this can be done purely by the player input? i.e forward/backward?

  4. #4
    Iron Guard
    Join Date
    Sep 2010
    Location
    Slovakia
    Posts
    588

    Default

    Yes, it is easy to implement.

    In player controller class use appropriate function (StartFire etc.) and increase speed of your train every click.

    Pseudocode:

    PC class:

    IncreaseVelocity = 1;

    exec function StartFire(byte FireModeNum)
    {
    MyTrain.Speed += IncreaseVelocity;
    }

    It will be little harder if u want to implement acceleration but it is possible.
    Czech and Slovak UDK site - www.udk-site.net-core.eu
    Space Shock project on STEAM GREENLIGHT

  5. #5
    Iron Guard
    Join Date
    Sep 2010
    Location
    Slovakia
    Posts
    588

    Default

    New version. Deleted "InvertedRotation", reverser and added startup location initialization. Speed < 0 is now backward movement.

    Code:
    class Train extends Actor placeable;
    
    var array<SplineActor> SplineCache;             //List of all SplineActors
    var float              Distance;                //Distance on the Spline to find a Location
    var() float              Speed;                 // Speed of train - you can assign it in editor
    var SplineActor        CurrentSplineActor;   
    var() SplineActor      StartingSplineActor;       // Position where will our train start - you can assign it in editor
    
    function PostBeginPlay()
    {
            super.PostBeginPlay();
            InitializeSplineActors();       // Create list of all SplineActors
            MoveToRail();                   // Moves train to StartingSplineActor
    }
    
    function InitializeSplineActors()
    {
    	local SplineActor Current;
    
    	foreach AllActors( class'SplineActor', Current)
    	{
    		SplineCache.AddItem( Current );
    		Current.nextOrdered = Current.GetBestConnectionInDirection(vect(0,1,0)); // Assign next spline actor
    		if(Current.nextOrdered != none)          
    		{
    			Current.nextOrdered.prevOrdered = Current; // Assign previous spline actor to prevordered var
    		}
    	}
    }
    
    function MoveToRail()
    {
        local Vector        RequiredLocation;        //Position on the spline we should be constrained to
    	local Vector        Direction;               //Direction we should be facing - rotation.
    	local float         StartDistance;           // lenght of spline component
    
      if(CurrentSplineActor==none)
      {
          CurrentSplineActor=StartingSplineActor; // Set our starting location as location of StartingSplineActor
      }
    
      StartDistance = 0;  // Normal move
    
      RequiredLocation = CurrentSplineActor.FindSplineComponentTo(CurrentSplineActor.NextOrdered).GetLocationAtDistanceAlongSpline(StartDistance); // Changing our distance along spline to vector
      Direction = Normal(CurrentSplineActor.FindSplineComponentTo(CurrentSplineActor.NextOrdered).GetTangentAtDistanceAlongSpline(StartDistance)); // Changing our distance along spline to direction vector and converting it to unit vector
    
      SetRotation(Rotator(Direction));
      SetLocation(RequiredLocation);
    }
    
    function Tick(float DeltaTime)    
    {
    	local Vector        RequiredLocation;        //Position on the spline we should be constrained to
    	local Vector        Direction;               //Direction we should be facing - rotation.
    	local float         MaxDistance;           // lenght of spline component
    
        super.Tick(DeltaTime);
           
        if(CurrentSplineActor==none)
        {
            CurrentSplineActor=StartingSplineActor; // Set our starting location as location of StartingSplineActor
        }
    
            //Assigning distance between CurrentSplineActor and next spline actor
            If(Speed > 0)
            {
                MaxDistance = CurrentSplineActor.FindSplineComponentTo(CurrentSplineActor.nextOrdered).GetSplineLength();
                    If((MaxDistance-Distance) > Speed) 
                    {
                            Distance += Speed;  // Normal move
                    }
                    else
                    {
    
                            Distance = Speed - (MaxDistance-Distance); // ! MaxDistance-Distance < Speed
                            CurrentSplineActor = CurrentSplineActor.nextOrdered; // Setting next actor as current spline //actor
                    }
                    RequiredLocation = CurrentSplineActor.FindSplineComponentTo(CurrentSplineActor.NextOrdered).GetLocationAtDistanceAlongSpline(Distance); // Changing our distance along spline to vector
                    Direction = Normal(CurrentSplineActor.FindSplineComponentTo(CurrentSplineActor.NextOrdered).GetTangentAtDistanceAlongSpline(Distance)); // Changing our distance along spline to direction vector and converting it to unit vector
    
                    SetRotation(Rotator(Direction));
                   	SetLocation(RequiredLocation);
            }
            else if(Speed < 0)  // Inverted Move
            {
                MaxDistance = CurrentSplineActor.prevOrdered.FindSplineComponentTo(CurrentSplineActor).GetSplineLength();
            	If(Distance > Speed)
                    {
                            Distance += Speed;
                    }
                    else
                    {
                            Distance = MaxDistance - (Speed - Distance);
                            CurrentSplineActor = CurrentSplineActor.prevOrdered;
                    }
    
                    RequiredLocation = CurrentSplineActor.FindSplineComponentTo(CurrentSplineActor.NextOrdered).GetLocationAtDistanceAlongSpline(Distance);           `log("RequiredLocation"@RequiredLocation);
                    Direction = Normal(CurrentSplineActor.FindSplineComponentTo(CurrentSplineActor.NextOrdered).GetTangentAtDistanceAlongSpline(Distance));
    
                    SetRotation(Rotator(Direction));
                    SetLocation(RequiredLocation);
            }
    }
    
    defaultproperties
    {
        Begin Object Class=DynamicLightEnvironmentComponent Name=MyLightEnvironment
        End Object
        Components.Add(MyLightEnvironment)
    
        Begin Object Class=StaticMeshComponent Name=Cursor
              Scale=0.4
              LightEnvironment=MyLightEnvironment
              CastShadow=true
             	bCastDynamicShadow=true
       	      bOwnerNoSee=false
              BlockRigidBody=false
              CollideActors=false
              BlockActors=false
              BlockZeroExtent=false
        StaticMesh=StaticMesh'EngineMeshes.Sphere'
        End Object
    
        Components.Add(Cursor)
    }
    Czech and Slovak UDK site - www.udk-site.net-core.eu
    Space Shock project on STEAM GREENLIGHT


 

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Copyright ©2009-2011 Epic Games, Inc. All Rights Reserved.
Digital Point modules: Sphinx-based search vBulletin skin by CompletevB.com.