summaryrefslogtreecommitdiff
path: root/ROUNDS/_Player/PlayerCollision.cs
blob: c6f2750d2e940ad1f02f2c580bc6f85f9cfff230 (plain)
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
using System;
using System.Collections;
using Photon.Pun;
using Sonigon;
using UnityEngine;

//重要
public class PlayerCollision : MonoBehaviour
{
	[Header("Sounds")]
	public SoundEvent soundBounce;

	[Header("Settings")]
	public LayerMask mask;

	private Vector2 lastPos;

	public bool checkForGoThroughWall = true;

	private int ignoreWallFor;

	private Collider2D col;

	private CircleCollider2D cirCol;

	private PlayerVelocity vel;

	private CharacterData data;

	public Action<Vector2, Vector2, Player> collideWithPlayerAction;

	public float bounceTreshold = 1f;

	private bool isBounce;

	public void IgnoreWallForFrames(int frames)
	{
		ignoreWallFor = frames;
	}

	private void Start()
	{
		data = GetComponent<CharacterData>();
		col = GetComponent<Collider2D>();
		cirCol = GetComponent<CircleCollider2D>();
		vel = GetComponent<PlayerVelocity>();
	}

	// 经过测试,注释掉fixedupdate,有点影响地面碰撞,但还是可以站在地面上

	// PlayerVelocity强制设置一个向下的速度后,角色并没有陷到地面以下,是因为这里的碰撞检测。如果注释掉,角色就会陷入地面以下

	private void FixedUpdate()
	{
		#region 检测墙,和地面无关(好像也有关)
		if (checkForGoThroughWall && ignoreWallFor <= 0)
		{
			RaycastHit2D raycastHit2D = default(RaycastHit2D);
			RaycastHit2D[] array = Physics2D.RaycastAll(lastPos, (Vector2)base.transform.position - lastPos, Vector2.Distance(base.transform.position, lastPos), mask);
			for (int i = 0; i < array.Length; i++)
			{
				if (!(array[i].transform.root == base.transform.root))
				{
					Debug.DrawLine(lastPos, array[i].point, Color.green, 1f);
					if (!(Vector2.Angle(array[i].normal, (Vector2)base.transform.position - lastPos) < 90f) && (!raycastHit2D.transform || array[i].distance < raycastHit2D.distance))
					{
						raycastHit2D = array[i];
					}
				}
			}
			if ((bool)raycastHit2D)
			{
				base.transform.position = raycastHit2D.point + raycastHit2D.normal * 0.5f;
				if (data.healthHandler.flyingFor > 0f)
				{
					DoBounce(raycastHit2D);
				}
			}
		}
		#endregion

		#region 碰撞检测
		ignoreWallFor--;
		lastPos = base.transform.position;
		float realRadius = cirCol.radius * base.transform.localScale.x;
		float innerRadius = cirCol.radius * base.transform.localScale.x * 0.75f;  // 
		// 以circlecollider的位置和大小为参考做碰撞检测
		RaycastHit2D[] array2 = Physics2D.CircleCastAll(lastPos, realRadius, (Vector2)base.transform.position - lastPos, Vector2.Distance(base.transform.position, lastPos), mask);
		for (int j = 0; j < array2.Length; j++)
		{
			if (array2[j].transform.root == base.transform.root) // 自己和自己碰撞
			{
				continue;
			}
			Vector2 characterPosition = base.transform.position;
			Vector2 point = array2[j].point;
			float distToHitpoint = Vector2.Distance(characterPosition, point);
			Vector2 dirFromHitpoint = (characterPosition - point).normalized;
			float realPushAmount = realRadius + (0f - distToHitpoint);
			float innerPushAmount = innerRadius + (0f - distToHitpoint);
            realPushAmount = Mathf.Clamp(realPushAmount, 0f, 10f);
            innerPushAmount = Mathf.Clamp(innerPushAmount, 0f, 10f);

			NetworkPhysicsObject component = array2[j].transform.GetComponent<NetworkPhysicsObject>();
			if ((bool)component)
			{
				component.Push(data);
			}

            //! 把角色往返方向推
            if (vel.simulated || !vel.isKinematic) // true
			{
				vel.transform.position += (Vector3)dirFromHitpoint * innerPushAmount; // 不是很重要,可以注释掉 
                if (Mathf.Abs(dirFromHitpoint.y) < 0.45f && Mathf.Abs(data.input.direction.x) > 0.1f && Vector3.Angle(data.input.direction, dirFromHitpoint) > 90f)
                {
                    data.TouchWall(dirFromHitpoint, point);
                }
                vel.velocity += dirFromHitpoint * realPushAmount * 10f * TimeHandler.timeScale;
                vel.velocity -= vel.velocity * realPushAmount * 1f * TimeHandler.timeScale;
            }

            Player componentInParent = array2[j].transform.GetComponentInParent<Player>();
			if (componentInParent != null && collideWithPlayerAction != null)
			{
				collideWithPlayerAction(point, realPushAmount * dirFromHitpoint, componentInParent);
			}

			if (data.healthHandler.flyingFor > 0f)
			{
				DoBounce(array2[j]);
			}
		}
        #endregion 

        lastPos = base.transform.position;
	}

	private void DoBounce(RaycastHit2D hit)
	{
		if (!(Vector2.Angle(data.playerVel.velocity, hit.normal) < 90f) && !isBounce && data.view.IsMine && data.playerVel.velocity.magnitude > bounceTreshold)
		{
			data.view.RPC("RPCADoBounce", RpcTarget.All, hit.normal, base.transform.position);
		}
	}

	[PunRPC]
	private void RPCADoBounce(Vector2 hit, Vector3 playerPos)
	{
		base.transform.position = playerPos;
		StartCoroutine(IDoBounce(Vector2.Reflect(data.playerVel.velocity, hit)));
		SoundManager.Instance.Play(soundBounce, base.transform);
	}

	public IEnumerator IDoBounce(Vector2 targetVel)
	{
		isBounce = true;
		data.stunHandler.AddStun(0.2f);
		data.healthHandler.CallTakeDamage(targetVel.normalized * 5f, base.transform.position);
		GamefeelManager.instance.AddGameFeel(targetVel.normalized * 4f);
		yield return new WaitForSeconds(0.25f);
		data.playerVel.velocity = targetVel;
		isBounce = false;
	}

	private void OnDisable()
	{
		isBounce = false;
	}
}