List.Contains() 总是错误的
List.Contains() is ALWAYS false
我正在 this 教程中制作游戏,主要使用他们的代码。统一的 list.contains() 方法对我来说总是 returns false。我检查了代码的其他部分,这似乎是唯一的问题。我正在为我的第一个 game jam 做这个,我已经坚持了一天了,所以如果你能帮忙的话,请帮忙!
else {
if (previousSelected == null) { // 3 Is it the first tile selected?
Debug.Log('6');
Select();
}
Debug.Log(GetAllAdjacentTiles().Contains(previousSelected.gameObject));
if (GetAllAdjacentTiles().Contains(previousSelected.gameObject))
{ // 1
Debug.Log('8');
SwapSprite(previousSelected.render); // 2
Debug.Log('3');
previousSelected.ClearAllMatches();
previousSelected.Deselect();
ClearAllMatches();
}
else { // 3
previousSelected.GetComponent<Tile>().Deselect();
Select();
}
}
这是它总是 returns 错误的部分:
if (GetAllAdjacentTiles().Contains(previousSelected.gameObject))
此外,这是完整代码
public class Tile : MonoBehaviour {
private static Color selectedColor = new Color(.5f, .5f, .5f, 1.0f);
private static Tile previousSelected = null;
private SpriteRenderer render;
private bool isSelected = false;
private Vector2[] adjacentDirections = new Vector2[] { Vector2.up, Vector2.down, Vector2.left, Vector2.right };
private bool matchFound = false;
void Awake() {
render = GetComponent<SpriteRenderer>();
}
private void Select() {
isSelected = true;
render.color = selectedColor;
previousSelected = gameObject.GetComponent<Tile>();
//SFXManager.instance.PlaySFX(Clip.Select);
}
private void Deselect() {
isSelected = false;
render.color = Color.white;
previousSelected = null;
}
void OnMouseDown() {
if (render.sprite == null || BoardManager.instance.IsShifting) {
return;
}
if (isSelected) { // 2 Is it already selected?
Debug.Log('5');
Deselect();
}
else {
if (previousSelected == null) { // 3 Is it the first tile selected?
Debug.Log('6');
Select();
}
Debug.Log(GetAllAdjacentTiles().Contains(previousSelected.gameObject));
if (GetAllAdjacentTiles().Contains(previousSelected.gameObject))
{ // 1
Debug.Log('8');
SwapSprite(previousSelected.render); // 2
Debug.Log('3');
previousSelected.ClearAllMatches();
previousSelected.Deselect();
ClearAllMatches();
}
else { // 3
previousSelected.GetComponent<Tile>().Deselect();
Select();
}
}
}
public void SwapSprite(SpriteRenderer render2) { // 1
if (render.sprite == render2.sprite) { // 2
return;
}
Sprite tempSprite = render2.sprite; // 3
render2.sprite = render.sprite; // 4
render.sprite = tempSprite; // 5
//SFXManager.instance.PlaySFX(Clip.Swap); // 6
}
private GameObject GetAdjacent(Vector2 castDir) {
RaycastHit2D hit = Physics2D.Raycast(transform.position, castDir);
//Debug.Log('1');
if (hit.collider != null) {
return hit.collider.gameObject;
}
return null;
}
private List<GameObject> GetAllAdjacentTiles() {
List<GameObject> adjacentTiles = new List<GameObject>();
for (int i = 0; i < adjacentDirections.Length; i++) {
adjacentTiles.Add(GetAdjacent(adjacentDirections[i]));
//Debug.Log(adjacentDirections.Length);
}
Debug.Log(adjacentTiles);
return adjacentTiles;
}
private List<GameObject> FindMatch(Vector2 castDir) { // 1
List<GameObject> matchingTiles = new List<GameObject>(); // 2
RaycastHit2D hit = Physics2D.Raycast(transform.position, castDir); // 3
while (hit.collider != null && hit.collider.GetComponent<SpriteRenderer>().sprite == render.sprite) { // 4
matchingTiles.Add(hit.collider.gameObject);
hit = Physics2D.Raycast(hit.collider.transform.position, castDir);
}
return matchingTiles; // 5
}
private void ClearMatch(Vector2[] paths) // 1
{
List<GameObject> matchingTiles = new List<GameObject>(); // 2
for (int i = 0; i < paths.Length; i++) // 3
{
matchingTiles.AddRange(FindMatch(paths[i]));
}
if (matchingTiles.Count >= 2) // 4
{
for (int i = 0; i < matchingTiles.Count; i++) // 5
{
matchingTiles[i].GetComponent<SpriteRenderer>().sprite = null;
}
matchFound = true; // 6
}
}
public void ClearAllMatches() {
if (render.sprite == null)
return;
ClearMatch(new Vector2[2] { Vector2.left, Vector2.right });
ClearMatch(new Vector2[2] { Vector2.up, Vector2.down });
if (matchFound) {
render.sprite = null;
matchFound = false;
//SFXManager.instance.PlaySFX(Clip.Clear);
}
}
}
在我看来,最可能的解释是寻找相邻图块的光线投射全部击中源图块并将其添加到列表中四次。如果是这样,则存在三种可能的解决方案:
- 转到编辑 -> 项目设置 -> Physics2d 并禁用 Raycasts Start In Colliders。这将意味着光线投射总是忽略它们开始的任何碰撞器,因此如果您需要该功能,将会导致问题。
- 在进行光线投射之前禁用源对象的碰撞器,然后再次启用它(例如,通过实际禁用组件或将其移动到忽略光线投射层)。
- 使用 RaycastAll 并在忽略源对象的情况下遍历结果。
我正在 this 教程中制作游戏,主要使用他们的代码。统一的 list.contains() 方法对我来说总是 returns false。我检查了代码的其他部分,这似乎是唯一的问题。我正在为我的第一个 game jam 做这个,我已经坚持了一天了,所以如果你能帮忙的话,请帮忙!
else {
if (previousSelected == null) { // 3 Is it the first tile selected?
Debug.Log('6');
Select();
}
Debug.Log(GetAllAdjacentTiles().Contains(previousSelected.gameObject));
if (GetAllAdjacentTiles().Contains(previousSelected.gameObject))
{ // 1
Debug.Log('8');
SwapSprite(previousSelected.render); // 2
Debug.Log('3');
previousSelected.ClearAllMatches();
previousSelected.Deselect();
ClearAllMatches();
}
else { // 3
previousSelected.GetComponent<Tile>().Deselect();
Select();
}
}
这是它总是 returns 错误的部分:
if (GetAllAdjacentTiles().Contains(previousSelected.gameObject))
此外,这是完整代码
public class Tile : MonoBehaviour {
private static Color selectedColor = new Color(.5f, .5f, .5f, 1.0f);
private static Tile previousSelected = null;
private SpriteRenderer render;
private bool isSelected = false;
private Vector2[] adjacentDirections = new Vector2[] { Vector2.up, Vector2.down, Vector2.left, Vector2.right };
private bool matchFound = false;
void Awake() {
render = GetComponent<SpriteRenderer>();
}
private void Select() {
isSelected = true;
render.color = selectedColor;
previousSelected = gameObject.GetComponent<Tile>();
//SFXManager.instance.PlaySFX(Clip.Select);
}
private void Deselect() {
isSelected = false;
render.color = Color.white;
previousSelected = null;
}
void OnMouseDown() {
if (render.sprite == null || BoardManager.instance.IsShifting) {
return;
}
if (isSelected) { // 2 Is it already selected?
Debug.Log('5');
Deselect();
}
else {
if (previousSelected == null) { // 3 Is it the first tile selected?
Debug.Log('6');
Select();
}
Debug.Log(GetAllAdjacentTiles().Contains(previousSelected.gameObject));
if (GetAllAdjacentTiles().Contains(previousSelected.gameObject))
{ // 1
Debug.Log('8');
SwapSprite(previousSelected.render); // 2
Debug.Log('3');
previousSelected.ClearAllMatches();
previousSelected.Deselect();
ClearAllMatches();
}
else { // 3
previousSelected.GetComponent<Tile>().Deselect();
Select();
}
}
}
public void SwapSprite(SpriteRenderer render2) { // 1
if (render.sprite == render2.sprite) { // 2
return;
}
Sprite tempSprite = render2.sprite; // 3
render2.sprite = render.sprite; // 4
render.sprite = tempSprite; // 5
//SFXManager.instance.PlaySFX(Clip.Swap); // 6
}
private GameObject GetAdjacent(Vector2 castDir) {
RaycastHit2D hit = Physics2D.Raycast(transform.position, castDir);
//Debug.Log('1');
if (hit.collider != null) {
return hit.collider.gameObject;
}
return null;
}
private List<GameObject> GetAllAdjacentTiles() {
List<GameObject> adjacentTiles = new List<GameObject>();
for (int i = 0; i < adjacentDirections.Length; i++) {
adjacentTiles.Add(GetAdjacent(adjacentDirections[i]));
//Debug.Log(adjacentDirections.Length);
}
Debug.Log(adjacentTiles);
return adjacentTiles;
}
private List<GameObject> FindMatch(Vector2 castDir) { // 1
List<GameObject> matchingTiles = new List<GameObject>(); // 2
RaycastHit2D hit = Physics2D.Raycast(transform.position, castDir); // 3
while (hit.collider != null && hit.collider.GetComponent<SpriteRenderer>().sprite == render.sprite) { // 4
matchingTiles.Add(hit.collider.gameObject);
hit = Physics2D.Raycast(hit.collider.transform.position, castDir);
}
return matchingTiles; // 5
}
private void ClearMatch(Vector2[] paths) // 1
{
List<GameObject> matchingTiles = new List<GameObject>(); // 2
for (int i = 0; i < paths.Length; i++) // 3
{
matchingTiles.AddRange(FindMatch(paths[i]));
}
if (matchingTiles.Count >= 2) // 4
{
for (int i = 0; i < matchingTiles.Count; i++) // 5
{
matchingTiles[i].GetComponent<SpriteRenderer>().sprite = null;
}
matchFound = true; // 6
}
}
public void ClearAllMatches() {
if (render.sprite == null)
return;
ClearMatch(new Vector2[2] { Vector2.left, Vector2.right });
ClearMatch(new Vector2[2] { Vector2.up, Vector2.down });
if (matchFound) {
render.sprite = null;
matchFound = false;
//SFXManager.instance.PlaySFX(Clip.Clear);
}
}
}
在我看来,最可能的解释是寻找相邻图块的光线投射全部击中源图块并将其添加到列表中四次。如果是这样,则存在三种可能的解决方案:
- 转到编辑 -> 项目设置 -> Physics2d 并禁用 Raycasts Start In Colliders。这将意味着光线投射总是忽略它们开始的任何碰撞器,因此如果您需要该功能,将会导致问题。
- 在进行光线投射之前禁用源对象的碰撞器,然后再次启用它(例如,通过实际禁用组件或将其移动到忽略光线投射层)。
- 使用 RaycastAll 并在忽略源对象的情况下遍历结果。