- Home /
Health regen script wont work properly
var gotHitTimer=0; var regentimer=0; var hurtsound : AudioClip; var waittime=5; var healthlastframe :float = 100; var walkSpeed = 6.0; var respawnpoint : GameObject; var runSpeed = 11.0; var dietimes = 0; // If true, diagonal speed (when strafing + moving forward or back) can't exceed normal move speed; otherwise it's about 1.4 times faster var limitDiagonalSpeed = true; var shadap : AudioClip; // If checked, the run key toggles between running and walking. Otherwise player runs if the key is held down and walks otherwise // There must be a button set up in the Input Manager called "Run" var toggleRun = false; var health :float =100; var jumpSpeed = 8.0; var gravity = 20.0;
// Units that player can fall before a falling damage function is run. To disable, type "infinity" in the inspector var fallingDamageThreshold = 10.0;
// If the player ends up on a slope which is at least the Slope Limit as set on the character controller, then he will slide down var slideWhenOverSlopeLimit = false;
// If checked and the player is on an object tagged "Slide", he will slide down it regardless of the slope limit var slideOnTaggedObjects = false;
var slideSpeed = 12.0;
// If checked, then the player can change direction while in the air var airControl = false;
// Small amounts of this results in bumping when walking down slopes, but large amounts results in falling too fast var antiBumpFactor = .75;
// Player must be grounded for at least this many physics frames before being able to jump again; set to 0 to allow bunny hopping var antiBunnyHopFactor = 1;
private var moveDirection = Vector3.zero; private var grounded = false; private var controller : CharacterController; private var myTransform : Transform; private var speed : float; private var hit : RaycastHit; private var fallStartLevel : float; private var falling = false; private var slideLimit : float; private var rayDistance : float; private var contactPoint : Vector3; private var playerControl = false; private var jumpTimer : int;
function Start () { controller = GetComponent(CharacterController); myTransform = transform; speed = walkSpeed; rayDistance = controller.height * .5 + controller.radius; slideLimit = controller.slopeLimit - .1; jumpTimer = antiBunnyHopFactor; oldPos = transform.position; }
function FixedUpdate() { var inputX = Input.GetAxis("Horizontal"); var inputY = Input.GetAxis("Vertical"); // If both horizontal and vertical are used simultaneously, limit speed (if allowed), so the total doesn't exceed normal move speed var inputModifyFactor = (inputX != 0.0 && inputY != 0.0 && limitDiagonalSpeed)? .7071 : 1.0;
if (grounded) {
var sliding = false;
// See if surface immediately below should be slid down. We use this normally rather than a ControllerColliderHit point,
// because that interferes with step climbing amongst other annoyances
if (Physics.Raycast(myTransform.position, -Vector3.up, hit, rayDistance)) {
if (Vector3.Angle(hit.normal, Vector3.up) > slideLimit)
sliding = true;
}
// However, just raycasting straight down from the center can fail when on steep slopes
// So if the above raycast didn't catch anything, raycast down from the stored ControllerColliderHit point instead
else {
Physics.Raycast(contactPoint + Vector3.up, -Vector3.up, hit);
if (Vector3.Angle(hit.normal, Vector3.up) > slideLimit)
sliding = true;
}
// If we were falling, and we fell a vertical distance greater than the threshold, run a falling damage routine
if (falling) {
falling = false;
if (myTransform.position.y < fallStartLevel - fallingDamageThreshold)
FallingDamageAlert (fallStartLevel - myTransform.position.y);
}
// If running isn't on a toggle, then use the appropriate speed depending on whether the run button is down
if (!toggleRun)
speed = Input.GetButton("Run")? runSpeed : walkSpeed;
// If sliding (and it's allowed), or if we're on an object tagged "Slide", get a vector pointing down the slope we're on
if ( (sliding && slideWhenOverSlopeLimit) || (slideOnTaggedObjects && hit.collider.tag == "Slide") ) {
var hitNormal = hit.normal;
moveDirection = Vector3(hitNormal.x, -hitNormal.y, hitNormal.z);
Vector3.OrthoNormalize (hitNormal, moveDirection);
moveDirection *= slideSpeed;
playerControl = false;
}
// Otherwise recalculate moveDirection directly from axes, adding a bit of -y to avoid bumping down inclines
else {
moveDirection = Vector3(inputX * inputModifyFactor, -antiBumpFactor, inputY * inputModifyFactor);
moveDirection = myTransform.TransformDirection(moveDirection) * speed;
playerControl = true;
}
// Jump! But only if the jump button has been released and player has been grounded for a given number of frames
if (!Input.GetButton("Jump"))
jumpTimer++;
else if (jumpTimer >= antiBunnyHopFactor) {
moveDirection.y = jumpSpeed;
jumpTimer = 0;
}
}
else {
// If we stepped over a cliff or something, set the height at which we started falling
if (!falling) {
falling = true;
fallStartLevel = myTransform.position.y;
}
// If air control is allowed, check movement but don't touch the y component
if (airControl && playerControl) {
moveDirection.x = inputX * speed * inputModifyFactor;
moveDirection.z = inputY * speed * inputModifyFactor;
moveDirection = myTransform.TransformDirection(moveDirection);
}
}
// Apply gravity
moveDirection.y -= gravity * Time.deltaTime;
// Move the controller, and set grounded true or false depending on whether we're standing on something
grounded = (controller.Move(moveDirection * Time.deltaTime) & CollisionFlags.Below) != 0;
}
function Update () { // If the run button is set to toggle, then switch between walk/run speed. (We use Update for this... // FixedUpdate is a poor place to use GetButtonDown, since it doesn't necessarily run every frame and can miss the event) if (toggleRun && grounded && Input.GetButtonDown("Run")){ speed = (speed == walkSpeed? runSpeed : walkSpeed); } if (health<1){ audio.PlayOneShot(shadap); transform.position = respawnpoint.transform.position; health=100; } if(health<100){ regen();
}
if(health>100){ health=100; }
Camera.main.GetComponent("ColorCorrectionEffect").rampOffsetR = (100-health)/150;
if(health!=healthlastframe){ regenwait(); } } // Store point that we're in contact with for use in FixedUpdate if needed function OnControllerColliderHit (hit : ControllerColliderHit) { contactPoint = hit.point; }
// If falling damage occured, this is the place to do something about it. You can make the player // have hitpoints and remove some of them based on the distance fallen, add sound effects, etc. function FallingDamageAlert (fallDistance : float) { Debug.Log ("Ouch! Fell " + fallDistance + " units!");
if(fallDistance>20) health=health-fallDistance/1.5;
} function OnGUI () { GUI.Label (Rect (30, 80, 100, 30), health.ToString());
} function Awake(){ transform.position = respawnpoint.transform.position; } function regen(){
while(regentimer==1){
health+=3;
yield;
}
if(health>100){
health=100;
}
}
function regenwait(){ regentimer=0; playhurtsound(); addblur(); regentimer=0; yield WaitForSeconds(10); regentimer=1; healthlastframe = health; }
function addblur(){ camera.main.GetComponent("BlurEffect").enabled=true; yield WaitForSeconds(1); camera.main.GetComponent("BlurEffect").enabled=false; }
function playhurtsound(){ if (Time.time > gotHitTimer) { audio.PlayOneShot(hurtsound); } gotHitTimer = Time.time + hurtsound.length;
}
@script RequireComponent(CharacterController)
Okay , in this script , i wait 10 seconds to start regenerating . I then regenerate but when im at 100 hp i continue regenerating for another 10 seconds. Also when im hit while regenerating i dont stop another 10 seconds but continue to regenerate. What am i doing wrong here?
Are you describing what does happen or what you want to happen?
You have a lot of yield statements in there that you don't really need. It complicates things as you can't be sure how long the script will yield for exactly.
Also fixed update should really be reserved for physics related functions, if you wanted things to behave relative to time you just multiply the result by Time.deltaTime.
Not really important but general na$$anonymous$$g conventions go by functions starting with capital letter and variables starting with lower case letters. It just makes things easier to read when typing code
If one of the posted answers solved your problem, please mark it as the accepted answer.
Answer by spinaljack · Jul 09, 2010 at 12:20 PM
Basically I'd get rid of all the yields you've got and use time stamps instead. Find the time that you were last hit and then only start regaining health when the game time is 10 seconds higher than the time stamp.
Change your regen script to this:
function ApplyDamage(points : float){ AddBlur(); health-=points; lastHit = Time.time; health = Mathf.Clamp(health,0,100); // clamp health if(health<=0) //dead }
function Regen(){
// start 10 seconds after the last time you were hit
if(Time.time-lastHit>10){
// regain 3 hit points every second
health+=Time.deltaTime*3;
health = Mathf.Clamp(health,0,100); // clamp health
}
}
Health is a float here but you can change my script to work with yours.
EDIT
Included AddBlur
And how to implement that with the healthlastframe i use to add the blur on screen? Sorry but im too lazy right now to do so but if you didnt $$anonymous$$d and it wouldnt be time consu$$anonymous$$g , can you post the full code with the snippet you gave me fully implemented?
Normally I charge $25 an hour for freelance work. I'm here to help, not do the work for you...
Answer by yeoldesnake 1 · Jul 14, 2010 at 12:47 PM
var lastHit; var gotHitTimer=0; var regentimer=0; var hurtsound : AudioClip; var waittime=5; var walkSpeed = 6.0; var respawnpoint : GameObject; var runSpeed = 11.0; var dietimes = 0; // If true, diagonal speed (when strafing + moving forward or back) can't exceed normal move speed; otherwise it's about 1.4 times faster var limitDiagonalSpeed = true; var shadap : AudioClip; // If checked, the run key toggles between running and walking. Otherwise player runs if the key is held down and walks otherwise // There must be a button set up in the Input Manager called "Run" var toggleRun = false; var health :float =100; var jumpSpeed = 8.0; var gravity = 20.0;
// Units that player can fall before a falling damage function is run. To disable, type "infinity" in the inspector var fallingDamageThreshold = 10.0;
// If the player ends up on a slope which is at least the Slope Limit as set on the character controller, then he will slide down var slideWhenOverSlopeLimit = false;
// If checked and the player is on an object tagged "Slide", he will slide down it regardless of the slope limit var slideOnTaggedObjects = false;
var slideSpeed = 12.0;
// If checked, then the player can change direction while in the air var airControl = false;
// Small amounts of this results in bumping when walking down slopes, but large amounts results in falling too fast var antiBumpFactor = .75;
// Player must be grounded for at least this many physics frames before being able to jump again; set to 0 to allow bunny hopping var antiBunnyHopFactor = 1;
private var moveDirection = Vector3.zero; private var grounded = false; private var controller : CharacterController; private var myTransform : Transform; private var speed : float; private var hit : RaycastHit; private var fallStartLevel : float; private var falling = false; private var slideLimit : float; private var rayDistance : float; private var contactPoint : Vector3; private var playerControl = false; private var jumpTimer : int;
function Start () { controller = GetComponent(CharacterController); myTransform = transform; speed = walkSpeed; rayDistance = controller.height * .5 + controller.radius; slideLimit = controller.slopeLimit - .1; jumpTimer = antiBunnyHopFactor; oldPos = transform.position; }
function FixedUpdate() { var inputX = Input.GetAxis("Horizontal"); var inputY = Input.GetAxis("Vertical"); // If both horizontal and vertical are used simultaneously, limit speed (if allowed), so the total doesn't exceed normal move speed var inputModifyFactor = (inputX != 0.0 && inputY != 0.0 && limitDiagonalSpeed)? .7071 : 1.0;
if (grounded) {
var sliding = false;
// See if surface immediately below should be slid down. We use this normally rather than a ControllerColliderHit point,
// because that interferes with step climbing amongst other annoyances
if (Physics.Raycast(myTransform.position, -Vector3.up, hit, rayDistance)) {
if (Vector3.Angle(hit.normal, Vector3.up) > slideLimit)
sliding = true;
}
// However, just raycasting straight down from the center can fail when on steep slopes
// So if the above raycast didn't catch anything, raycast down from the stored ControllerColliderHit point instead
else {
Physics.Raycast(contactPoint + Vector3.up, -Vector3.up, hit);
if (Vector3.Angle(hit.normal, Vector3.up) > slideLimit)
sliding = true;
}
// If we were falling, and we fell a vertical distance greater than the threshold, run a falling damage routine
if (falling) {
falling = false;
if (myTransform.position.y < fallStartLevel - fallingDamageThreshold)
FallingDamageAlert (fallStartLevel - myTransform.position.y);
}
// If running isn't on a toggle, then use the appropriate speed depending on whether the run button is down
if (!toggleRun)
speed = Input.GetButton("Run")? runSpeed : walkSpeed;
// If sliding (and it's allowed), or if we're on an object tagged "Slide", get a vector pointing down the slope we're on
if ( (sliding && slideWhenOverSlopeLimit) || (slideOnTaggedObjects && hit.collider.tag == "Slide") ) {
var hitNormal = hit.normal;
moveDirection = Vector3(hitNormal.x, -hitNormal.y, hitNormal.z);
Vector3.OrthoNormalize (hitNormal, moveDirection);
moveDirection *= slideSpeed;
playerControl = false;
}
// Otherwise recalculate moveDirection directly from axes, adding a bit of -y to avoid bumping down inclines
else {
moveDirection = Vector3(inputX * inputModifyFactor, -antiBumpFactor, inputY * inputModifyFactor);
moveDirection = myTransform.TransformDirection(moveDirection) * speed;
playerControl = true;
}
// Jump! But only if the jump button has been released and player has been grounded for a given number of frames
if (!Input.GetButton("Jump"))
jumpTimer++;
else if (jumpTimer >= antiBunnyHopFactor) {
moveDirection.y = jumpSpeed;
jumpTimer = 0;
}
}
else {
// If we stepped over a cliff or something, set the height at which we started falling
if (!falling) {
falling = true;
fallStartLevel = myTransform.position.y;
}
// If air control is allowed, check movement but don't touch the y component
if (airControl && playerControl) {
moveDirection.x = inputX * speed * inputModifyFactor;
moveDirection.z = inputY * speed * inputModifyFactor;
moveDirection = myTransform.TransformDirection(moveDirection);
}
}
// Apply gravity
moveDirection.y -= gravity * Time.deltaTime;
// Move the controller, and set grounded true or false depending on whether we're standing on something
grounded = (controller.Move(moveDirection * Time.deltaTime) & CollisionFlags.Below) != 0;
}
function Update () { // If the run button is set to toggle, then switch between walk/run speed. (We use Update for this... // FixedUpdate is a poor place to use GetButtonDown, since it doesn't necessarily run every frame and can miss the event) if (toggleRun && grounded && Input.GetButtonDown("Run")){ speed = (speed == walkSpeed? runSpeed : walkSpeed); }
if(health>100){
health=100;
}
if(health<100)
Regen();
Camera.main.GetComponent("ColorCorrectionEffect").rampOffsetR = (100-health)/150; }
// Store point that we're in contact with for use in FixedUpdate if needed function OnControllerColliderHit (hit : ControllerColliderHit) { contactPoint = hit.point; }
// If falling damage occured, this is the place to do something about it. You can make the player // have hitpoints and remove some of them based on the distance fallen, add sound effects, etc. function FallingDamageAlert (fallDistance : float) { Debug.Log ("Ouch! Fell " + fallDistance + " units!");
if(fallDistance>20) ApplyDamage(health-fallDistance/1.5);
} function OnGUI () { GUI.Label (Rect (30, 80, 100, 30), health.ToString());
} function Awake(){ transform.position = respawnpoint.transform.position; } function ApplyDamage(points : float){ playhurtsound(); AddBlur(); health-=points; lastHit = Time.time; health = Mathf.Clamp(health,0,100); // clamp health if(health<=0){ audio.PlayOneShot(shadap); transform.position = respawnpoint.transform.position; health=100; } }
function Regen(){
// start 10 seconds after the last time you were hit
if(Time.time-lastHit>10){
// regain 3 hit points every second
health+=40*Time.deltaTime;
health = Mathf.Clamp(health,0,100); // clamp health
}
}
function AddBlur(){ camera.main.GetComponent("BlurEffect").enabled=true; yield WaitForSeconds(1); camera.main.GetComponent("BlurEffect").enabled=false; }
function playhurtsound(){ if (Time.time > gotHitTimer) { audio.PlayOneShot(hurtsound); } gotHitTimer = Time.time + hurtsound.length;
}
@script RequireComponent(CharacterController)
There you go you lazy person...
Your answer
Follow this Question
Related Questions
How do i set health to regenerate over a specified range of time? 1 Answer
Sidescroller health bar collision script with regen? 1 Answer
HealthPack Script Problem... 1 Answer
health bar 2 Answers