※목차
1. 선, 공 그리기
2. 배경 이동
3. 플레이어 행동
4. 적과 탄환
5. 전체 스크립트 및 게임 다운로드
1. 선, 공 그리기
스크립트)
1) CreateLine(), UpdateLine() 함수
- 마우스 드래그할 때 마우스의 좌표들을 List로 저장하여 Line Renderer를 이용해 그 정점들을 잇는 선을 그립니다.
그리고 Edge Collider를 이용해 플레이어가 밟을 수 있는 플랫폼을 만듭니다.
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
|
//선 생성 함수
void CreateLine()
{
//선 생성 준비
currentLine = Instantiate(linePrefab, Vector3.zero, Quaternion.identity);
lineRenderer = currentLine.GetComponent<LineRenderer>();
edgeCollider = currentLine.GetComponent<EdgeCollider2D>();
fingerPositions.Clear();
//선 생성
line_StartPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
fingerPositions.Add(line_StartPos);
fingerPositions.Add(line_StartPos);
lineRenderer.SetPosition(0, fingerPositions[0]);
lineRenderer.SetPosition(1, fingerPositions[1]);
edgeCollider.points = fingerPositions.ToArray();
}
//선 그리기 함수
void UpdateLine(Vector2 newFingerPos)
{
fingerPositions.Add(newFingerPos);
lineRenderer.positionCount++;
lineRenderer.SetPosition(lineRenderer.positionCount - 1, newFingerPos);
edgeCollider.points = fingerPositions.ToArray();
}
|
cs |
2) EraseLIne() 함수
- RaycastHit와 LayerMask를 이용한 layerchk()함수를 사용하여 선 혹은 공인지 아닌지 구분합니다.
그 후 선 혹은 공이면 마우스 우클릭으로 오브젝트 삭제가 가능합니다.
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
|
void Update()
{
(생략)
//마우스 오른쪽 버튼을 눌렀을 때
else if (Input.GetMouseButtonDown(1))
{
if(!isRedBall)
EraseLIne("Line");
else
EraseLIne("Ball");
}
(생략)
}
//선 지우기 함수
void EraseLIne(string layerName)
{
RaycastHit2D hit = layerChk(layerName);
if (hit.collider != null)
{
GameObject target = hit.collider.gameObject;
if (!isRedBall)
Destroy(target);
else
Destroy(target.transform.parent.gameObject);
}
}
//특정 레이어의 RaycastHit2D를 반환하는 함수
RaycastHit2D layerChk(string layerName)
{
Vector2 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
int layerMask = 1 << LayerMask.NameToLayer(layerName);
RaycastHit2D hit = Physics2D.Raycast(pos, Vector2.zero, 0f, layerMask);
return hit;
}
|
cs |
3)선을 그릴 때와 공을 생성할 때를 구분하기 위해서 처음과 끝 마우스 좌표가 같으면 물리엔진이 작용하는 공이
생성되도록 조건문을 사용했습니다.
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
|
void Update()
{
(생략)
//마우스 왼쪽 버튼을 땔 때 && 빨간 공이 아닐 때 && 연필심 양이 남았을 때
else if (Input.GetMouseButtonUp(0) && !isRedBall && !isEmpty)
{
audio.Stop();
//선 첫 지점과 끝 지점 위치가 같을 때 점에 중력이 작용
if (Vector2.Distance(line_EndPos, line_StartPos) < 0.1f && lineRenderer.positionCount < 3)
{
PencilQuantity(-3); //연필심 양 -3
currentLine.GetComponent<Rigidbody2D>().isKinematic = false;
currentLine.GetComponent<EdgeCollider2D>().edgeRadius = 0.08f;
FindObjectOfType<RendererToCollider>().EdgePosCreate();
#region 빨간색 버튼
//빨간색 버튼 생성
GameObject go = Instantiate(ballPrefab, line_EndPos, Quaternion.identity);
//선을 빨간색 공의 부모로 설정
go.transform.SetParent(currentLine.transform);
#endregion
}
isDrawing = false;
player.GetComponent<Animator>().SetBool("Drawing", false);
}
}
|
cs |
4) RaycastHit와 layerChk() 함수를 사용하여 공인지 아닌지 구분 후 공이면 크기와 질량이 커질 수 있도록
RedBall.cs의 ScaleUp() 함수를 사용했습니다.
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
|
public class DrawLine : MonoBehaviour
{
(생략)
//커서가 빨간공 위에 있는지 체크하는 함수
void RedBallChk()
{
RaycastHit2D hit = layerChk("Ball");
if (hit.collider != null)
isRedBall = true;
else
isRedBall = false;
}
}
public class RedBall : MonoBehaviour
{
(생략)
//공 크기 커지게 하는 함수
public void ScaleUp(Transform hitCollider)
{
if (hitCollider.localScale.x < 3.5) //공 최대 크기 3.5
{
hitCollider.localScale = new Vector2(hitCollider.localScale.x * 1.5f, hitCollider.localScale.y * 1.5f);
transform.parent.GetComponent<Rigidbody2D>().mass *= 1.6f;
}
}
}
|
cs |
2. 카메라와 배경 이동
스크립트)
1) Reposition() 함수를 사용해 방향값 dir만 가져와서 카메라 위치에 따라 배경 이미지를 앞뒤로 이동시킵니다.
2) CameraMove클래스에서 조건문으로 맵 밖으로 나가지 않게 하기 위해 카메라 이동에 제한을 둡니다.
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
63
64
65
66
67
68
|
public class BackgroundScroll : MonoBehaviour
{
Transform camera_Tran;
Transform player;
float width;
void Awake()
{
BoxCollider2D backgoundCollider = GetComponent<BoxCollider2D>();
width = backgoundCollider.size.x;
}
void Start()
{
player = GameObject.Find("Player").transform;
camera_Tran = GameObject.Find("Main Camera").transform;
}
void Update()
{
transform.position = new Vector2(transform.position.x, camera_Tran.position.y);
//배경이 움직이는 방향
if (camera_Tran.position.x - transform.position.x >= width)
Reposition(1);
else if (transform.position.x - camera_Tran.position.x > width)
Reposition(-1);
}
//배경 이동 함수
void Reposition(int dir)
{
Vector2 offset = new Vector2(width * 2f * dir, 0);
transform.position += (Vector3)offset;
}
}
public class CameraMove : MonoBehaviour
{
Transform player;
void Start()
{
player = GameObject.Find("Player").transform;
}
void Update()
{
transform.position = new Vector3(player.position.x, player.position.y, -10);
//카메라 이동 x축 제한
if(transform.position.x < 0f)
{
transform.position = new Vector3(0, transform.position.y, -10);
}
//카메라 이동 y축 제한
if (transform.position.y < 0f)
{
transform.position = new Vector3(transform.position.x, 0f, -10);
}
else if (transform.position.y > 3f)
{
transform.position = new Vector3(transform.position.x, 3f, -10);
}
}
}
|
cs |
3. 플레이어 행동
스크립트)
1) 조건문을 사용하여 선을 그리는 중에 이동하지 못하도록 제약을 뒀습니다.
2) PlayerFoot에 Circle Collider를 만들고 GroundCheck.cs 스크립트로 점프할 때 땅 위에 있는지 없는지
체크하도록 만들었습니다.
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
public class PlayerController : MonoBehaviour
{
(생략)
//플레이어 이동
void playerMove()
{
//플레이어가 죽은 상태가 아니고 그리는 중이 아닐 때 움직일 수 있다는 조건
if (!isDead && !FindObjectOfType<DrawLine>().isDrawing)
{
//횡이동
int horizontal = (int)Input.GetAxisRaw("Horizontal");
//이동할 때
if (horizontal != 0)
{
transform.localScale = new Vector3(horizontal, 1, 1);
rb2D.velocity = new Vector2(walk_Speed * horizontal * Time.deltaTime, rb2D.velocity.y);
//땅위에 있으면
if (isGrounded)
animator.SetBool("Walk", true);
}
//움직이지 않을 때
else
{
rb2D.velocity = new Vector2(0, rb2D.velocity.y);
animator.SetBool("Walk", false);
}
//점프할 때
if (Input.GetKeyDown(KeyCode.Space) && jumpCount < 1 && isGrounded)
{
isGrounded = false;
jumpCount++;
rb2D.velocity = new Vector2(0, 0);
rb2D.AddForce(transform.up * jump_Force);
animator.SetBool("Jump", true);
}
}
}
}
public class GroundCheck : MonoBehaviour
{
public GameObject player;
private void OnCollisionEnter2D(Collision2D collision)
{
//땅이나 선에 닿을시
if (collision.transform.tag == "Line" || collision.transform.tag == "Ground")
{
player.GetComponent<PlayerController>().animator.SetBool("Jump", false);
}
}
private void OnCollisionStay2D(Collision2D collision)
{
//땅이나 선에 서있을 때
if (collision.transform.tag == "Line" || collision.transform.tag == "Ground")
{
player.GetComponent<PlayerController>().jumpCount = 0; //점프한 횟수 초기화
player.GetComponent<PlayerController>().isGrounded = true; //땅위에 있는 상태 true
}
}
private void OnCollisionExit2D(Collision2D collision)
{
//땅이나 선에서 떨어졌을 때
if (collision.transform.tag == "Line" || collision.transform.tag == "Ground")
{
player.GetComponent<PlayerController>().isGrounded = false; //땅위에 있는 상태 false
}
}
}
|
cs |
3) 플레이어가 그리는 도중에도 자연스러운 동작이 되도록 DrawingReady와 IdleToDrawing 애니메이션을 따로
만들었습니다.
4. 적과 탄환
스크립트)
1) Time.deltaTime을 사용하여 발사 시간을 조절했습니다.
2) Instantiate로 탄환을 생성하고 탄환은 생성될 때 적(parent)이 바라보고 있는 방향으로 발사되도록 했습니다.
3) 탄환이 환경 오브젝트하고 충돌하면 탄환만 삭제하도록 했고, 선이나 공과 충돌하면 선과 공까지 같이
삭제되도록 했습니다.
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
|
public class BulletSpawner : MonoBehaviour
{
public GameObject bulletPrefab;
float delta = 0;
public float spawnTime = 3f;
void Update()
{
delta += Time.deltaTime;
//발사 시간 간격
if(delta > spawnTime)
{
delta = 0f;
Vector3 x = new Vector3(1.75f, 0, 0);
//총알 생성
GameObject bullet = Instantiate(bulletPrefab, transform.position + (x * transform.localScale.x), transform.rotation);
bullet.transform.SetParent(transform);
}
}
}
public class CannonBullet : MonoBehaviour
{
public float speed;
Rigidbody2D rb2D;
void Start()
{
rb2D = GetComponent<Rigidbody2D>();
//적이 바라보고 있는 방향으로 등속도 발사
transform.localScale = new Vector3(-transform.localScale.x * transform.parent.localScale.x, 1, 1);
rb2D.velocity = transform.parent.localScale.x * transform.right * speed;
}
private void OnCollisionEnter2D(Collision2D collision)
{
//선이나 공에 닿을 때
if(collision.collider.tag == "Line" || collision.collider.tag == "Ball")
{
Destroy(collision.gameObject); //선이나 공 삭제
Destroy(gameObject); //자기 자신 삭제
}
//오브젝트, 땅, 플레이어와 닿을 때
else if(collision.collider.tag == "Object" || collision.collider.tag == "Ground" || collision.collider.tag == "Player")
{
Destroy(gameObject); //자기 자신 삭제
}
}
}
|
cs |
5. 전체 스크립트 및 게임 다운로드
전체 스크립트 : https://nemesis32.tistory.com/111
스크립트 다운로드 : drive.google.com/file/d/1dsq-0ReAjvYbUKretr7Uh3xTyjqQ3XTe/view?usp=sharing
게임 다운로드 : https://drive.google.com/open?id=1EyiiJnlTkhNiJ7smA9tstt4pcB7HBB8G
'프로그래밍' 카테고리의 다른 글
Zombie Survive 스크립트, 기능 설명 (0) | 2020.06.01 |
---|---|
Zombie Survive 전체 스크립트 (0) | 2020.06.01 |
Line Drawing 전체 스크립트 (0) | 2020.05.13 |
DigDog 스크립트 설명 (0) | 2020.05.08 |
DigDog 전체 스크립트 (0) | 2020.05.07 |