The question is answered, right answer was accepted. It was totaly in comments, but it worked!
Enemy makes player glitch through walls
So I made a player controller, which includes a wall mechanisem since i don't use physics to move. here's all the playerControl script: using UnityEngine; using System.Collections;
public class PlayerControl: MonoBehaviour {
Vector3 pos;
public Animation ani;
int dir;
BoxCollider2D boxCollider;
public LayerMask blockingLayer;
bool[] isAllowd;
// Use this for initialization
void Start () {
pos = GetComponent<Transform> ().position;
dir = 0;
isAllowd = new bool[4]{ true, true, true, true };
boxCollider = GetComponent<BoxCollider2D> ();
}
// Update is called once per frame
void Update () {
GetComponent<Animator> ().speed = 0;
if (Input.GetKey (KeyCode.D)&&advanceMove(0.03f,0)) {
pos.x += 0.03f;
dir = 0;
GetComponent<Animator> ().SetInteger ("dir", dir);
GetComponent<Animator> ().speed = 1;
}
if (Input.GetKey (KeyCode.A)&&advanceMove(-0.03f,0)) {
pos.x -= 0.03f;
dir = 2;
GetComponent<Animator> ().SetInteger ("dir", 2);
GetComponent<Animator> ().speed = 1;
}
if (Input.GetKey (KeyCode.W)&&advanceMove(0,0.03f)) {
pos.y += 0.03f;
dir = 1;
GetComponent<Animator> ().SetInteger ("dir", 1);
GetComponent<Animator> ().speed = 1;
}
if (Input.GetKey (KeyCode.S)&&advanceMove(0,-0.03f)) {
pos.y -= 0.03f;
dir = 3;
GetComponent<Animator> ().SetInteger ("dir", 3);
GetComponent<Animator> ().speed = 1;
}
GetComponent<Transform> ().position = pos;
if (transform.childCount != 0) {
transform.GetChild (0).gameObject.GetComponent<WeapondData>().setAttack(dir);
}
}
protected bool move (float xDir, float yDir, int adder)
{
RaycastHit2D hit;
Vector2 start = transform.position;
if (xDir != 0) {
start.x += (GetComponent<BoxCollider2D> ().size.x / 2) * (xDir / Mathf.Abs (xDir));
start.y += (adder * (GetComponent<BoxCollider2D> ().size.y / 2));
} else if (yDir != 0) {
start.y += (GetComponent<BoxCollider2D> ().size.y / 2) * (yDir / Mathf.Abs (yDir));
start.x += (adder * (GetComponent<BoxCollider2D> ().size.x / 2));
}
Vector2 end = start + new Vector2 (xDir, yDir);
boxCollider.enabled = false;
hit = Physics2D.Linecast (start, end, blockingLayer);
boxCollider.enabled = true;
//Check if anything was hit
if(hit.transform == null)
{
return true;
}
return false;
}
private bool advanceMove(float xDir, float yDir)
{
return (move (xDir, yDir, 0) && move (xDir, yDir, 1) && move (xDir, yDir, -1));
}
}
I also made an enemy which is still until you get close enough, then he chases you. here's the basicEnemy script: using UnityEngine; using System.Collections;
public class basicEnemy : MonoBehaviour {
/** enemy needs:
* a weapond
* health
* basic movement AI
* */
float hp;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
searchAndDestroy ();
}
protected Vector3 lockOn()
{
Collider2D[] col = Physics2D.OverlapCircleAll (transform.position, 3);
Vector2 t;
float minLength=9999;
Vector3 returned=transform.position;
for (int i = 0; i < col.Length; i++) {
t = (Vector2)(transform.position - col [i].transform.position);
if ((minLength > t.magnitude)&&col[i].gameObject.tag=="Player") {
minLength = t.magnitude;
returned = col [i].transform.position;
}
}
Debug.Log (returned);
return returned;
}
protected bool inRange()
{
return true;
}
protected void animate(Vector3 target)
{
float x = Mathf.Abs (transform.position.x - target.x);
float y = Mathf.Abs (transform.position.y - target.y);
float axis = Mathf.Max (x,y);
if (x == axis) {
GetComponent<Animator> ().SetInteger ("dir", 0);
if (transform.position.x > target.x) {
GetComponent<SpriteRenderer> ().flipX = true;
} else {
GetComponent<SpriteRenderer> ().flipX = false;
}
}
if (y == axis) {
if (transform.position.y > target.y) {
GetComponent<Animator> ().SetInteger ("dir", 1);
} else {
GetComponent<Animator> ().SetInteger ("dir", 3);
}
}
GetComponent<BoxCollider2D> ().size = Vector3.Scale (transform.localScale, GetComponent<SpriteRenderer> ().sprite.rect.size);
}
protected void searchAndDestroy()
{
Vector3 target = lockOn ();
animate (target);
transform.position = Vector3.MoveTowards (transform.position, target, 0.02f);
}
}
The thing I noticed during testing is, although the playerControl works perfectly, WHEN THE ENEMY LOCKS ON YOU the player can suddenly glitch through walls. Now it's not a smooth movement, but you can defenetly glitch there. Did anyone notice anything in basicEnemy that can inturrupt the functioning of playerControl?
"Glitch through walls" implies a collider not functioning properly. Colliders and physics are done on the FixedUpdate() schedule, but both of those above scripts operate within Update().
It's not uncommon to move something within the Update() call, but you cannot guarantee that movement to obey any physics that may not be calculated at the time of your movement.
Since your enemy seems to be calling a Physics2D function (OverlapCircleAll()) outside of the physics update, this might be causing issues.
For responsiveness, it can be convenient to store player input within Update(), then relay it to the movement portion during FixedUpdate(). This ensures that all movement involving a collider correlates to Unity's physics engine and the collider calculations.
I tried to move the movement of the player to fixedUpdate and moved the searchAndDestroy function from update to fixedUpdate, now there are 2 new problems cause progra$$anonymous$$g is fun: First, the player display no animation, and second, when i touch a wall the player starts teleporting between 2 points like crazy
Unrelated, you may eventually want to consider referencing your player's collider ahead of time ins$$anonymous$$d of repeatedly calling GetComponent().
As for movement, you may have a logical flaw in your player script:
hit = Physics2D.Linecast (start, end, blockingLayer);
Here, you're making a linecast from (presumably) where your player is starting to where they are ending movement. This is a practical decision, but the vectors you are providing may have an issue.
You are incrementing the Start vector by (normalized direction magnitude * collider radius), but then adding it again into End. The result seems to be a line from your player's intended movement position to their position if they were to continue movement.
$$anonymous$$oreover, you're adjusting the X,Y components without knowing that a change in those directions is taking place at all. $$anonymous$$eeping with the same style you had, have you considered:
Vector2 start = transform.position;
Vector2 end = transform.position;
if (xDir != 0) {
end.x += adder * (GetComponent<BoxCollider2D> ().size.x / 2) * (xDir / $$anonymous$$athf.Abs (xDir));
}
if (yDir != 0) {
end.y += adder * (GetComponent<BoxCollider2D> ().size.y / 2) * (yDir / $$anonymous$$athf.Abs (yDir));
}
hit = Physics2D.Linecast (start, end, blockingLayer);
Here, X and Y changes require input to happen and Start will always be your current position.
Actually, what is the conceptual purpose of that "adder" value? I assume it was to check different directions, but you know the direction you want to move / check. That can probably be removed...
First of all, I'm not sure if it's clear so i'll say it, The adjustments to START are because usually it will draw a line from the $$anonymous$$IDDLE of the player, aka the location of it's pivot point, and then half the player can still get in the wall. Sometimes, It even got the pivot point INTO the collider, thus making the player get stuck.
The adder is ment for the 3 tests, since the it's a line from the middle, the head and the feet can still go through walls, thus I check 3 positions - the middle, and the two edges, Thus there is no point in multiplying adder to the movement direction. what I can and i'm trying a I'm writing this, is adjust the end's secondary axis, which creats a cone of ray which provide me a somewhat better effect.
And it worked! here's what I did:
Vector2 start = transform.position;
Vector2 end = start + new Vector2 (xDir, yDir);
if (xDir != 0) {
end.x += ((GetComponent<BoxCollider2D> ().size.x / 2) * (xDir / $$anonymous$$athf.Abs (xDir)));
end.y += (adder * (GetComponent<BoxCollider2D> ().size.y / 2));
} else if (yDir != 0) {
end.y += (GetComponent<BoxCollider2D> ().size.y / 2) * (yDir / $$anonymous$$athf.Abs (yDir));
end.x += (adder * (GetComponent<BoxCollider2D> ().size.y / 2));
}
Now still remains only one problem, which is presumably the easiest one: the player animation still dont work with the new fixedUpdate. Got any ideas?
I think you might be able to simplify a lot of this by moving the rigidbody without all of these linecast checks, but glad to hear it works somewhat!
As for the animator, where is the animator related stuff being called? Update() still?
Follow this Question
Related Questions
2D moving Script 1 Answer
[SOLVED] Problems creating a Sprite through script 0 Answers
My knockback script is not working 0 Answers
Trying to simulate SNES party snake, non-grid. 0 Answers
I can't figure out why this variable is not updating 0 Answers