-- 检测碰撞物,如果发生碰撞则进行位移
function LColliderBDY:BDYFixedUpdate(velocity)
local isGround = false
local isWall = false
-- 检测和什么碰,2d碰撞范围一般比实际要大,因为AABB要大一点,为了精确碰撞,需要自己实现
local contactColliders = CS.Tools.Instance:Collider2DOverlapCollider(self.collider, self.filter) -- 这个函数其实Collider2D.OverlapCollider,用来手动检测碰撞,这边因为lua的缘故封装了一下
-- 最终位移坐标
local finalOffset_x = 0
local finalOffset_y = 0
for p, k in pairs(contactColliders) do
if self.collider.bounds:Intersects(k.bounds) then
local up, down, left, right = false, false, false, false
local go = k.attachedRigidbody.gameObject
if go:GetComponent(typeof(CS.UnityEngine.Rigidbody2D)) ~= nil and go.name == "test" then -- 如果是地图块
local name = utils.split(k.name, ",")
local num = tonumber(name[#name]) -- 地图块最后一个数字作为bit
if num | 14 == 15 then --位操作,算出这个方块朝哪个方向进行碰撞,一个方块可以有多个碰撞方向,这部分随意设计,只需要能知道这个collider的判定方向,用layermask什么都行
up = true
end
if num | 13 == 15 then --位操作
down = true
end
if num | 11 == 15 then --位操作
left = true
end
if num | 7 == 15 then --位操作
right = true
end
elseif go:GetComponent(typeof(CS.XLuaTest.LuaBehaviour)) ~= nil then -- 是游戏object,则只允许左右进行碰撞,LuaBehaviour是用来调用lua的脚本,雨女无瓜
left = true
right = true
else
return false, false
end
local menseki = utils.getBoundsIntersectsArea(self.collider.bounds, k.bounds)
if menseki.magnitude > 0 then -- 无视多少面积设置,先不设
-- 算2个collider之间距离,主要是为了法线
local cd2d = self.collider:Distance(k)
local a = CS.UnityEngine.Vector3(cd2d.pointA.x, cd2d.pointA.y, 0)
local b = CS.UnityEngine.Vector3(cd2d.pointB.x, cd2d.pointB.y, 0)
local normal = -CS.UnityEngine.Vector3(cd2d.normal.x, cd2d.normal.y, 0)
CS.UnityEngine.Debug.DrawLine(a, a + normal, CS.UnityEngine.Color.red)
CS.UnityEngine.Debug.DrawLine(b, b + normal, CS.UnityEngine.Color.yellow)
-- 做碰撞法线与行进方向的点积
-- local projection = CS.UnityEngine.Vector2.Dot(velocity.normalized, normal) -- 没用到,有需要可以自己看情况加
local offset_x = 0
local offset_y = 0
-- 左移,右移
if self.collider.bounds.center.x < k.bounds.center.x then
if left and CS.UnityEngine.Vector2.Dot(velocity.normalized, CS.UnityEngine.Vector2(-1, 0)) <= 0 then -- 如果碰撞朝向与行进方向相反,则求出位移坐标
offset_x = -menseki.x
end
else
if right and CS.UnityEngine.Vector2.Dot(velocity.normalized, CS.UnityEngine.Vector2(1, 0)) <= 0 then
offset_x = menseki.x
end
end
-- 上移,下移
if self.collider.bounds.center.y > k.bounds.center.y then
if up and CS.UnityEngine.Vector2.Dot(velocity.normalized, CS.UnityEngine.Vector2(0, 1)) <= 0 then
offset_y = menseki.y
end
else
if down and CS.UnityEngine.Vector2.Dot(velocity.normalized, CS.UnityEngine.Vector2(0, -1)) <= 0 then
offset_y = -menseki.y
end
end
if (up or down) and (left or right) then -- 如果同时满足上下和左右方向同时存在的情况,则根据碰撞方向来筛选掉另一个轴的位移
offset_x = offset_x * math.abs(normal.x)
offset_y = offset_y * math.abs(normal.y)
end
-- 留下最小位移坐标
if velocity.x > 0 then
if offset_x < finalOffset_x then
finalOffset_x = offset_x
end
else
if offset_x > finalOffset_x then
finalOffset_x = offset_x
end
end
if velocity.y > 0 then
if offset_y < finalOffset_y then
finalOffset_y = offset_y
end
else
if offset_y > finalOffset_y then
finalOffset_y = offset_y
end
end
if go:GetComponent(typeof(CS.UnityEngine.Rigidbody2D)) ~= nil and go.name == "test" then -- 判断是不是撞到地面,这样写不好,以后再优化
if finalOffset_x ~= 0 then
isWall = true
end
if finalOffset_y > 0 then
isGround = true
end
end
end
end
end
-- 更新自身位置
self.collider.attachedRigidbody.position = self.collider.attachedRigidbody.position + CS.UnityEngine.Vector2(finalOffset_x, finalOffset_y)
return isGround, isWall
end
Directly on the code, call the code fixedupdate where the code is written in lua
Remember rigidbody2d set Kinematic, useFullKinematicContacts set to false, because we own realization collision, no unity of the collision oncolliderenter like, put this off may improve performance 8
Talk about ideas
Because the unity of aabb collision with box2d trigger range than the range defined to be large, so for pixel games, there will be pixel difference, affect the actual picture, such as standing on the ground sometimes vacated pixels high off the ground a
Moreover, the game is basically a block of pixels determination, but also with what is unlikely to friction, rebound, the geometry of the collision, simple I could add, so their impact is to achieve a good choice
See Official Collider2D.OverlapCollider with the API, the collision was detected, allows to obtain the impactor collision orientation (up, down, left, right), and their collider collider is detected at each detecting bounds, then the intersection
See their area was calculated collision position of an object, whether moving direction and facing toward their object allows collision (dot product is less than 0), i.e. the offset x and y axes of displacement required, based on its own position and to leave minimum offset direction, with the moving direction of the normal to write code may look good points, the last update position rigidbox
Just provide ideas, not the