이제 타워를 만들 것이다.

타워는 마땅한 이미지를 못구해 일단 도사할아버지랑 마법사를 타워로 설정했다.





타워는 몬스터를 때려야하는데 어떻게 처리할까 하다가 Collider를 사용하기로 했다.

그래서 도사할아버지한테 Rigidbody와 Circle Collider를 넣어줬다.

이후 중력을 받지않게 중력은 0으로. 충돌하여 밀려나지않게하기 위해 is Trigger를 체크해주었다.

그리고 넓은 범위를 공격하기 위해 콜라이더의 반지름값을 1로 넓혔음.




이제 타워 스크립트를 만들어 넣어준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class Tower : MonoBehaviour {
 
    public GameObject bullet = null;
    private GameObject closeEnemy = null;
 
    private List<GameObject> collEnemys = new List<GameObject>();
    private float fTime = 0;
    // Use this for initialization
    void Start () {
    }
    
    // Update is called once per frame
    void Update () {
        fTime += Time.deltaTime;
        if(collEnemys.Count > 0)
        {
            GameObject target = collEnemys[0];            
            if (gameObject.tag == "Tower1")
            {
                if (target != null && fTime > 1.0f)
                {
                    fTime = 0.0f;
                    var aBullet = Instantiate(bullet, transform.position, Quaternion.identity, transform);
                    aBullet.GetComponent<Lamp>().targetPosition = (target.transform.position - transform.position).normalized;
                    aBullet.transform.localScale = new Vector3(0.5f, 0.5f);
                }
            }
            else if(gameObject.tag == "Tower2")
            {
                if (target != null && fTime > 0.5f)
                {
                    fTime = 0.0f;
                    var aBullet = Instantiate(bullet, transform.position, Quaternion.identity, transform);
                    Vector3 dir = (target.transform.position - transform.position).normalized;
                    float angle = Vector2.SignedAngle(Vector2.down, dir);
                    Quaternion qut = new Quaternion();
                    qut.eulerAngles = new Vector3(00, angle);
                    aBullet.transform.rotation = qut;
                    aBullet.transform.position += dir * 1.0f;
                }
            }
        }
    }
 
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.tag == "Enemy")
            collEnemys.Add(collision.gameObject);
    }
 
    private void OnTriggerExit2D(Collider2D collision)
    {
        foreach (GameObject go in collEnemys)
        {
            if (go == collision.gameObject)
            {
                collEnemys.Remove(go);
                break;
            }
        }
    }
}
cs

적들에게는 Enemy라는 태그를 주고 이 태그를 가진 적들과 충돌하면 collEnemys라는 List에 적을 저장한다.

그리고 적들이 충돌범위에서 나가면 List에서 적을 삭제한다.


이후 범위안에 있는 적들의 카운트가 1 이상이면(적이 존재하면) 타워의 종류에 따라 다른 탄을 생성하고

탄에게 적의 위치쪽 방향을 넘겨준다. 


타워1은 1초마다 적에게 탄을 던지며, 타워2는 0.5초마다 적에게 전기를 쏜다.




1번째 탄은 적방향으로 계속 날아가며 부모와 거리가 벌어지거나 화면밖으로 나가면 탄이 삭제된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Lamp : MonoBehaviour {
 
    public Vector3 targetPosition = Vector3.zero;
    public GameObject ExplosionParticle = null;
    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        transform.Translate(targetPosition * Time.deltaTime * 3.0f);
 
        // 나와 부모의 사이가 일정거리(1.5f) 도달하면 삭제
        float distance = Vector3.Distance(transform.position, transform.parent.position);
        if (distance > 1.5f)
        {
            Destroy(gameObject);
        }
 
        if(transform.position.x < -0.64f || transform.position.x > 13.44f || transform.position.y < -0.64f || transform.position.y > 8.32f)
        {
            Destroy(gameObject);
        }
    }
}
cs


2번째 탄(전기)은 생성 후 0.5초가 지나면 스스로 삭제된다.

1
2
3
4
5
6
7
8
9
10
11
12
public class Thunder : MonoBehaviour {
 
    // Use this for initialization
    void Start () {
        Destroy(gameObject, 0.5f);
    }
    
    // Update is called once per frame
    void Update () {
        
    }
}
cs





이제 탄에 Tag를 넣어준 후 몬스터의 스크립트에 충돌부분을 추가한다.

몬스터에게 hp를 준 후 충돌한게 탄이면 hp를 감소시키고 탄(부딪힌것)을 삭제한다.

hp가 0이되면 몬스터도 삭제하게 만든다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.tag == "Bullet")
    {
        hp--;
        Destroy(collision.gameObject);
    }
 
    if (collision.tag == "Thunder")
    {
        hp--;
        Destroy(collision.gameObject, 0.2f);
    }
 
    if (hp <= 0)
    {
        Destroy(gameObject);
    }
}
cs

전기는 바로 사라지니 어색해서 0.2초 뒤에 사라지게 만듬.





실행화면

td_tower.mp4


이제 타워의 충돌범위 안에 적이 나타나면 타워가 탄을 쏘게되고 

탄이 적과 충돌하면 적의 hp가 감소되어 적이 죽게된다.






스플래시탄 만들기

이제 충돌체크는 탄에서 할것이기 때문에 몬스터의 스크립트에 있는 탄 충돌부분을 제거한다.

그리고 탄에서 탄이 사라질때 스플래시 데미지를 입히고 사라지도록 스크립트를 변경하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 나와 부모의 사이가 일정거리(1.5f) 도달하면 삭제
float distance = Vector3.Distance(transform.position, transform.parent.position);
if (distance > 1.5f)
{
    // 나(램프)에서 1.0f 반경에 있는 애들을 전부 찾음
    Collider2D[] hitsCol = Physics2D.OverlapCircleAll(transform.position, 1.0f);
 
    // 찾은애들에게 전부 1뎀
    foreach (Collider2D hit in hitsCol)
    {
        if (hit.gameObject.tag == "Enemy")
        {
            hit.gameObject.GetComponent<Mob1>().damage(1);
        }
    }
 
    Instantiate(ExplosionParticle, transform.position, Quaternion.identity);
    Destroy(gameObject);
}
cs

Physics2D.OverlapCircleAll을 사용하면 해당좌표에서 원으로 반지름 1.0f 안에 있는 적들을 전부 찾아준다.

이렇게 foreach를 돌면서 찾은 적들에게 전부 데미지를 주는 것이다.



몬스터에는 일정량의 데미지를 주는 함수를 새로 만들어줬다.

1
2
3
4
5
6
7
8
9
public void damage(int dam)
{
    hp -= dam;
 
    if (hp <= 0)
    {
        Destroy(gameObject);
    }
}
cs





실행화면

td_splash.mp4


이펙트는 별로지만 스플래시데미지는 잘 들어간다.

Posted by misty_
,