- Home /
Scripting Issues on the Player with Laser
@Harinezumi I have some issues with my laser system, and many of that question was resolve in here link to the question
Another question here is about my Player script, what is wrong about it that the knockback time is too long?
using UnityEngine;
using System.Collections;
public class PlayerControllerScript : MonoBehaviour {
public float maxSpeed = 10f;
public float jumpForce = 700f;
bool facingRight = true;
Animator anim;
bool grounded = false;
public Transform groundCheck;
public float groundRadius = 0.2f;
public LayerMask whatIsGround;
public float move;
public float score;
public float spawnX, spawnY;
public int jumpConter;
public float knockback;
public float knockbackLength;
public float knockbackCount;
public bool knockFromRight;
private Rigidbody2D rb2d;
public float timer = 5f;
public void Start ()
{
rb2d = gameObject.GetComponent<Rigidbody2D> ();
anim = GetComponent<Animator>();
spawnX = transform.position.x;
spawnY = transform.position.y;
}
public void Update()
{
if (Input.GetKeyDown ("space") && jumpConter < 2) {
if ((jumpConter == 0 && grounded) || (jumpConter == 1)) {
anim.SetBool ("Ground", false);
rb2d.AddForce (Vector2.up * jumpForce);
grounded = true;
rb2d.velocity = (new Vector2 (move * maxSpeed * Time.deltaTime, rb2d.velocity.y));
jumpConter++;
}
}
}
public void FixedUpdate()
{
grounded = Physics2D.OverlapCircle (groundCheck.position, groundRadius, whatIsGround.value);
float move = Input.GetAxis ("Horizontal");
anim.SetBool ("Ground", grounded);
anim.SetFloat ("vSpeed", rb2d.velocity.y);
anim.SetFloat ("Speed", Mathf.Abs (move));
if (knockbackCount <= 0) {
rb2d.velocity = new Vector2 (move * maxSpeed, rb2d.velocity.y);
} else {
if (knockFromRight)
rb2d.velocity = new Vector2 (-knockback * 2f, knockback);
if (!knockFromRight)
rb2d.velocity = new Vector2 (knockback * 2f, knockback);
knockbackCount -= Time.deltaTime;
}
if (move > 0 && !facingRight)
Flip ();
else if (move < 0 && facingRight)
Flip ();
if (timer > 0) {
timer -= Time.deltaTime;
DamagePostProcessing.damage = true;
return;
} else {
DamagePostProcessing.damage = false;
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.layer == LayerMask.NameToLayer ("killObjects") || col.gameObject.layer == LayerMask.NameToLayer ("dieCollider"))// || col.gameObject.layer == LayerMask.NameToLayer ("Enemy"))
transform.position = new Vector3 (spawnX, spawnY, transform.position.z);
jumpConter = 0;
grounded = true;
if (col.transform.tag == "MovingPlatform")
{
transform.parent = col.transform;
}
}
void OnCollisionExit2D (Collision2D col)
{
if (col.transform.tag == "MovingPlatform")
{
transform.parent = null;
}
}
void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.layer == LayerMask.NameToLayer ("food")) {
Destroy (col.gameObject);
score++;
}
if (col.gameObject.layer == LayerMask.NameToLayer ("Enemy")) {
knockbackCount = knockbackLength;
timer = 5f;
if (transform.position.x < col.transform.position.x)
knockFromRight = true;
else
knockFromRight = false;
}
}
}
If you need to here is the script that was made by the last question in the link above
@Harinezumi Hello again, I added a question as you said. If you can, please try to resolve this issue, thanks!
Answer by Harinezumi · Mar 22, 2018 at 01:27 PM
I'm assuming that what you want is to move (knockback) the player when it is hit by the laser, and this effect should last knockbackCount
seconds (it helps a lot if you explain what you are trying to achieve, maybe even a short description of your game).
I strongly suspect that the issue is that as long as the raycast in the OneLaserScript is hitting the player, it will add to knockbackCount
, increasing more than once how long the player is knocked back. Instead of directly modifying knockbackCount
from OneLaserScript, you should encapsulate the logic into PlayerControllerScript (basically hide it from outside). Something like this:
// add this to PlayerControllerScript
public void Knockback (float knockbackDuration, bool knockFromRight) {
if (knockbackCount <= 0) { // if not being knocked back
knockbackCount += knockBackDuration;
this.knockFromRight = knockFromRight;
timer += 5;
}
}
// replace the part after PlayerControllerScript pcs = ... in OneLaserScript with this:
pcs.Knockback(1, spottedLeft);
This does basically the same thing, but is a lot cleaner.
Should I remove something from the Player script or just add this line of code below?
After tried this pcs.knockback(1, spottedLeft); Console shows that "PlayerControllerScript.knockback" is inaccessible due its protection level. But it is public, is there move about this protection level?
HitByLaser()
is a new function to be added by itself to PlayerControllerScript
. As far as I could see, you don't need to remove anything, it does almost the same as what you were doing in OneLaserScript
.
The error that you get is because the function is with an upper-case $$anonymous$$, but you also have a variable knockback
with lower-case k. That variable is private (which is good).
Please try to work a bit on figuring out what the error messages are. These are more program$$anonymous$$g related issues than Unity. With some practice at program$$anonymous$$g, understanding how things work, and knowing what the error messages mean you will be able to develop your game a lot faster.
I added the new function as you said.
I noticed that knockback with upper-case k is not exist, and added just knockback as I typed earlier. Please explain why we call for private variable and its good, because I thought that you cant call for these variables.
So the Console show these massages:
Hi @Harinezumi ! Do you have time right now to help resolve the issues? :)
Answer by Rembo4Fight · Mar 26, 2018 at 06:38 PM
@Harinezumi Please try to help, I think we almost get it done!
I think the bug is more about how things are set up. Can you please share both of the scripts and how the player and laser objects are set up? Please share the code using pastebin.com.
Okay, so I will start with the player :
It contains two colliders one is circle and box collider.
Inside the player game object, there is are sprites and a ground check.
Second is the laser:
It contains simple hit point with the particle system in it.
Second, it has a simple sprite for laser, box collider, and simple script to move back and forth. Inside this sprite, it has ray cast which is checking for the player on the left and right directions (each one have a start and the ending) And the script itself which contains everything.
If you need, I will send detailed screenshots of the player and the laser, but I think I added them to our consideration.
Thanks for the detailed description.
I think the main problem comes from directly modifying rigidbody.velocity
- the scripting reference directly says you should not do that, except for special cases. Ins$$anonymous$$d, I think you should add a one time force in the desired direction, much bigger than knockback
, because you only apply it once. So in $$anonymous$$nockback()
you should use rigidbody.AddForce()
, and remove the rb2d.velocity = ...
part in FixedUpdate()
. Please try this if it works.
Note, however, that there are other small issues that might interfere with this solution, so this might not work immediately. A bit later, when I have time, I will clean up these small issues and respond with the corrected scripts.
Your answer
Follow this Question
Related Questions
Trouble with fieldInfo.SetValue() and arrays 1 Answer
C# How to make moves/damage class? 2 Answers
Health Regen Stop After Damage 1 Answer
I can't place a script in the objects. 0 Answers
I need help with my spell dealing damage over time. 1 Answer