Results 1 to 11 of 11
  1. #1

    Default Flickering Health Bar

    Hi everyone,
    I have an issue with flickering health bars above pawns. I implemented it after http://www.moug-portfolio.info/index...-basics-canvas, where the idea that each pawn displays its own HP bar makes a lot of sense. So in my pawns I make a call the call
    Code:
     GetALocalPlayerController().myHUD.AddPostRenderedActor(self);
    and in the same pawn class I override the function
    Code:
     simulated event PostRenderFor(PlayerController PC, Canvas Canvas, vector CameraPosition, vector CameraDir)
    where I display the health bar.
    It is very straightforward and all works well with a few pawns on screen. But with a small crowd of 6 or 7 pawns, the HP bars start flickering and disappearing. I uploaded a short video of what I see on screen.
    Is there a problem with PostRenderFor? Or should I handle health bars differently?

  2. #2

  3. #3

    Default

    Sure, here is the PostRenderFor:
    Code:
    simulated event PostRenderFor(PlayerController PC, Canvas Canvas, vector CameraPosition, vector CameraDir)
    {
        local Vector lPosition, lTextSize;
        local Font previous_font;
        local float lHealthSize;
    	local float lBackgroundOffset;
    	local SkeletalMeshSocket socket;
    
    	if (Health <= 0)
    		return ; // no display for the dead.
    	
        //We store the font and restore it at the end, otherwise it will mess up the drawing of the rest of the HUD.
        previous_font = Canvas.Font;
        Canvas.Font = class'Engine'.Static.GetMediumFont();
        
        socket = Mesh.GetSocketByName('S_Hud');
    	if (socket != none)
    	{
    		lPosition = Mesh.GetBoneLocation(socket.BoneName);
    	}
    	else
    	{ // if there is no socket, put it above the eyes.
    		lPosition = Location;
    		lPosition.Z = lPosition.Z+EyeHeight;
    	}
        lPosition = Canvas.Project(lPosition);
        
        Canvas.TextSize(Name, lTextSize.X, lTextSize.Y); 
        
        // actor name
        Canvas.SetPos(lPosition.X - lTextSize.X/2,lPosition.Y);
    //    Canvas.SetDrawColor(255,128,128,255);
        Canvas.DrawText(Name,true);
    
    	if (mIsFocused)
    	{
    		lBackgroundOffset = 18;
    	}
    	else
    	{
    		lBackgroundOffset = 0;
    	}
    	lPosition.Y = lPosition.Y  - 20;
    
    	// This is the healthbar background
        Canvas.SetPos(lPosition.X - 45,lPosition.Y - lBackgroundOffset);
    	Canvas.DrawTile(HudIcons, 91, 18+lBackgroundOffset, 16, 19-lBackgroundOffset, 91,18+lBackgroundOffset);
    
    	// actual healthbar
    	lHealthSize=91*Health/HealthMax;
    	Canvas.SetPos(lPosition.X - 45,lPosition.Y);
    	Canvas.DrawTile(HudIcons, lHealthSize, 18, 16, 40, lHealthSize, 18);
    	
        Canvas.Font = previous_font;
    }
    and as suggested in the link above, the AddPostRenderedActor is called here:
    Code:
    auto state InitializingState
    {
    	function bool AttachHud()
    	{
    		local PlayerController lAPlayerController;
    
    		lAPlayerController = GetALocalPlayerController();
    		if (lAPlayerController != none)
    		{
    			lAPlayerController.myHUD.AddPostRenderedActor(self);
    			return true;
    		}
    		
    		return false; // didn't work, need to try again
    	}
    Begin:
    	if (AttachHud())
    	{
    		GotoState('InitializedState');
    	}
    	goto 'Begin';
    }
    
    state InitializedState
    {}

  4. #4
    Boomshot
    Join Date
    Aug 2011
    Posts
    2,365

    Default

    I can't see anything obvious to cause that effect. They are blinking at the same time which is curious, might indicate the problem is higher up the chain possibly in the hud itself.

    One thing you are missing is a check to determine if they are infront/behind the camera before projecting.

    Code:
    if( CameraDir dot (lPosition - CameraPos) > 0.0 )
    {
        // project and display
    }
    else
    {
        // position is behind the camera, so skip it and return
    }

  5. #5

    Default

    I'll add your check.
    I'll also try to reproduce the behavior on a small test project to see whether something comes up.

    Thanks Spoof!

  6. #6
    Boomshot
    Join Date
    Aug 2011
    Posts
    2,365

    Default

    You could place a `log at the top of the PostRenderFor event and check the timestamps it produces. If there are gaps then the function itself isn't getting called and the problem is somewhere else. If they're consistent then it's something within the function.

  7. #7

    Default

    Yes, I had tried adding the log right after the last "local" in PostRenderFor, and indeed there are gaps in the logging when the health bars don't display.

  8. #8

    Default

    Ok, there must be something wrong with the way I do it. I reproduce it with very little code and one pawn on screen.
    From what I understand, I need to:
    1. Set bShowOverlays=true in my HUD
    2. Somewhere inside the Pawn code call GetALocalPlayerController().myHUD.AddPostRenderedA ctor(self)
    3. In the same pawn, implement PostRenderFor


    So I created those 3 classes in a new TestUC package:
    Code:
    class TestHUD extends HUD;
    
    defaultproperties
    {
    	bShowOverlays=true
    }
    Code:
    class TestGame extends GameInfo;
    
    defaultproperties
    {
    	HUDType=class'TestUC.TestHUD'
    }
    Code:
    class TestHPBar extends Pawn 
    	placeable;
    
    simulated event PostRenderFor(PlayerController PC, Canvas Canvas, vector CameraPosition, vector CameraDir)
    {
        local Vector lPosition, lTextSize;
    
    `log("PostRenderFor called");
    
    	lPosition = Location;
    	lPosition.Z = lPosition.Z+EyeHeight;
    
    	if( CameraDir dot (lPosition - CameraPosition) > 0.0 )
    	{
    		lPosition = Canvas.Project(lPosition);
    		Canvas.TextSize(Name, lTextSize.X, lTextSize.Y); 
    
    		// actor name
    		Canvas.SetPos(lPosition.X - lTextSize.X/2,lPosition.Y);
        	Canvas.DrawText(Name,true);
    	}
    	// else position is behind the camera, so skip it and return
        
    }
    
    auto state InitializingState
    {
    	function bool AttachHud()
    	{
    		local PlayerController lAPlayerController;
    
    `log("trying init");
    
    		lAPlayerController = GetALocalPlayerController();
    		if (lAPlayerController != none)
    		{
    			lAPlayerController.myHUD.AddPostRenderedActor(self);
    			return true;
    		}
    		
    		return false; // didn't work, need to try again
    	}
    Begin:
    
    `log("begin init");
    
    	if (AttachHud())
    	{
    		GotoState('InitializedState');
    	}
    	goto 'Begin';
    }
    
    state InitializedState
    {
    Begin:
    `log("init done");
    }
    
    DefaultProperties
    {
        Begin Object class=SkeletalMeshComponent Name=MySkeletalMesh
    		SkeletalMesh=SkeletalMesh'CH_IronGuard_Male.Mesh.SK_CH_IronGuard_MaleA'
        End Object
        Mesh=MySkeletalMesh
        Components.Add(MySkeletalMesh)
    }
    Compile, start UDK, drop the TestHPBar pawn in the default startup level, change the game type to TestUC.TestGame in the World info and start the game.
    What I observe is the pawn hanging in the level with no HUD most of the time. But if I fly around it, the HUD displays and flickers. The PostRenderFor logging only shows up when the HUD displays.
    I have the March 2012 UDK release.

    I can't figure out a next step to troubleshoot. Any idea?
    Last edited by fredito; 05-31-2012 at 01:14 PM.

  9. #9

  10. #10

  11. #11

    Default

    oh dear. Well, I see a May release on the web site, I think I'll go through an upgrade I guess.

    Hey Spoof, thanks for your time!


 

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.