[英]How to detect if 3 or more objects are in contact at the same time (linked by a fourth object) [C# Unity]
How can I tell if 3 or more objects are in touch at the same time?如何判断是否有 3 个或更多物体同时接触?
This is what I'm trying to do:这就是我想要做的:
Let's say you have a game, where there is an eye stone and a moon stone, and they need to be connected to the skull stone to win.假设您有一款游戏,其中有眼石和月石,它们需要与骷髅石相连才能获胜。
You can use fire stones to extend the reach of the skull stone.您可以使用火石来扩大骷髅石的作用范围。
So if you want to win the level, the eye and the moon need to be connected to the skull.所以要想通关,眼睛和月亮需要连接到头骨上。
This is what I've tried:这是我试过的:
Using OnTriggerEnter2D and a series of bool queries使用 OnTriggerEnter2D 和一系列 bool 查询
It does work except for the part that I can't seem to be able to make it check if two or more are connected, for example, it can tell me that the skull is either touching the eye, or the moon, but not both at the same time.它确实有效,除了我似乎无法让它检查是否有两个或更多连接的部分,例如,它可以告诉我头骨正在接触眼睛或月亮,但不能同时接触两者同时。
Using Linecast to add objects to an array使用 Linecast 将对象添加到数组
This, I assume would work, except that I guess the line would detect any object in line with another object, regardless of distance.我认为这会起作用,除了我猜这条线会检测到与另一个 object 一致的任何 object,无论距离如何。
Also, not sure what the most efficient way of adding them into an array to check would be, or even if that would be the best way of checking contact.此外,不确定将它们添加到数组中以进行检查的最有效方法是什么,或者即使这将是检查联系人的最佳方法。
Below are some screenshots of what I'm trying to do:以下是我正在尝试做的一些截图:
Objects are apart:对象是分开的:
Now Skull touches eye and moon, win condition met:现在头骨接触眼睛和月亮,满足获胜条件:
If eye and moon are further apart, player can use fire to extend contact:如果眼睛和月亮相距较远,玩家可以使用火来扩大接触:
Thanks a lot!非常感谢!
I think I've solved it changing Tags on runtime.我想我已经解决了它在运行时更改标签的问题。
So the fire has a script now that it changes its own tag from Fire to Activated Fire if it touches the skull or another activated fire, this is with an OnTriggerStay2D and then the Totem checks to see if an activated fire or the skull is touching it.所以火现在有一个脚本,如果它接触到头骨或另一个激活的火,它会将自己的标签从火更改为激活的火,这是使用 OnTriggerStay2D 然后图腾检查是否有激活的火或头骨正在接触它.
It works!有用!
Also, if an ActivatedFire stops touching the Skull it becomes a Fire again此外,如果 ActivatedFire 停止接触 Skull,它会再次变成火
It would appear to me (and please correct me if I'm wrong, and ignore this answer) that your game is grid based, assuming that's the case, you can very easily keep track of your tiles and on a movement/creation/whatever event, scan for nearby neighbors and recursively look for the pattern you are looking for.在我看来(如果我错了请纠正我,并忽略这个答案)你的游戏是基于网格的,假设是这种情况,你可以很容易地跟踪你的瓷砖和运动/创造/无论什么事件,扫描附近的邻居并递归地寻找你正在寻找的模式。
If this is the case and your game is grid-based with whole numbers (ints), this approach will likely help you out a lot in the future;如果是这种情况,并且您的游戏是基于网格的整数 (ints),这种方法可能会在未来帮助您很多; as it's very simple, straight forward and dirt cheap performance wise.
因为它非常简单、直接,而且性能非常便宜。
In every scene I like to have a 'handler' object with a handler script that is constantly monitoring important objects that have an 'object' script, usually the win condition runs in the handler... in this script I would constantly check for the 'activated' parameter of those objects found in the scene with the 'object' script... This object script inside each object will be controlling individually their 'activated' parameter.在每个场景中,我都喜欢有一个“处理程序” object 和一个处理程序脚本,该脚本不断监视具有“对象”脚本的重要对象,通常获胜条件在处理程序中运行......在这个脚本中我会不断检查使用“对象”脚本在场景中找到的那些对象的“激活”参数...每个 object 中的这个 object 脚本将单独控制它们的“激活”参数。 Checking in each collision if the colliding object is an 'activated state' or if its the skull.... if so... Then change its own variable or tag to whatever the 'handler script is monitoring... When all objects in the list are in an activated state you win...
如果碰撞 object 是“激活状态”或者它的头骨......检查每次碰撞......如果是这样......然后将其自己的变量或标签更改为“处理程序脚本正在监视的任何东西......当所有对象在该列表在激活的 state 中,您赢了...
Handler.cs: Game starts... Looks for objects that have a' Object.cs' script and saves them into a list of the script type. Handler.cs:游戏开始...寻找具有'Object.cs'脚本的对象并将它们保存到脚本类型的列表中。 In a loop the handler is checking the 'activated' variable from the script of each object saved into the list of objects found.... If they are all activated or true.... You win.
在一个循环中,处理程序正在检查每个 object 脚本中保存到找到的对象列表中的“激活”变量……如果它们都被激活或为真……你赢了。 And you just need to drag and drop prebafs that have the Object.cs script.
您只需拖放具有 Object.cs 脚本的 prebaf。
Object.cs: Object.cs:
Here check for the collisions, when you collide with something check if that something has an 'Object.cs' script and check their 'activated' variable, if its activated... Cange its own variable to 'activated' or true or how ever you want to check it ik the handler script... In your example all stones need the same condition 'that the thing they are colliding with is in an activated state and that the skull is the first thing in the activated state when game begins... If we want to add many different objects with many different actions... We could just add a case statement that compares each colission different in order to change their activated parameter.在这里检查碰撞,当您与某物发生碰撞时检查该物体是否具有“Object.cs”脚本并检查它们的“激活”变量,如果它被激活...将其自己的变量更改为“激活”或 true 或如何你想用处理程序脚本检查它......在你的例子中,所有的石头都需要相同的条件'他们正在碰撞的东西在激活的 state 中并且头骨是游戏开始时激活的 state 中的第一件事。 .. 如果我们想添加许多具有许多不同动作的不同对象......我们可以只添加一个 case 语句来比较每个碰撞的不同,以更改它们的激活参数。 Here an example of the concept:
这里有一个概念的例子:
public bool activated;
public string type:
//add extra variables
Start() {
//if my type is = 'skull' then change my activated state to 'truel'... else make it false
//make extra variables false hasFire etc
}
OnTriggeEnter2D() {
Switch(type) {
case "fire" :
//check if the thing we collided with has a object script and if the activated variable is true... Ifso then make own variable true and If the objwct touches thw skull everything works fine since thw skull variable has been set in the start method
break;
case "totem" :
//Same as fire... It just needs to be next to something activated... fire or skull
break;
case "skullOnlyTotem" :
//thia collision will check if the tag of the objevt we collided is the skull tag... If so the totem is activated, activated fire doesn't work with this tototem because we are not checking the activated parameter only for the skull tag
break;
case "waterTotem" :
//here we can have a condition that needs only a colission with a object that has a water tag and nothing more
break;
case "obsidianTotem" :
//here we can have a totem that needs fire and water to be activated since we need two conditions we will add to extra variables to the script, the hasFire bool and the hasWater bool. These will be set to false on start and here we will check their state... First if what we collided is in the activated state then we are next to a fire... if so.. Set hasfire =true then check if that thing we collided has tag =water... If so hasWater = true ; finally
Compare if two conditions are true if so... Set the activated variable to true
break;
case "aLotOfConditions" :
//for ten conditions you will need 10 new variables and set them all to false at start and in each collision check the tag belong to any of its clnditions if so turn variable true... At last check if all true if so... Activate...
break;
}
}
Here we can scale up the functionality a lot just adding more to the case statement and changing the tag names... Making prefabs with diferent image and type name... Then just drop them in the scene.... Two scripts...在这里,我们可以扩展功能很多,只需向 case 语句添加更多内容并更改标签名称......使用不同的图像和类型名称制作预制件......然后将它们放入场景中......两个脚本...... .
Handler - > finds objects and checks activated variable Handler -> 查找对象并检查激活的变量
Object - >has activated variable and checks colissions with a case for every type using a conbination of tags and the activated variable Object -> 已激活变量并使用标签和激活变量的组合检查每种类型的案例冲突
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.