Viewmodel Problem

So, i tried to make so viewmodel will move back when colliding with wall (mostly to fix shooting through walls), like devs made it in experience called town :

…I’ve managed to get something like this :

Can someone explain why viewmodel act so weird? and how do i fix it?

Piece of code ( Inside of RunService.RenderStepped ) :

Viewmodel.PrimaryPart.CFrame = Camera.CFrame * CollideOffset

local Origin = Viewmodel.PrimaryPart
local Muzzle = Viewmodel:WaitForChild("MUZZLE")

local Num = (Origin.Position - Muzzle.Position).Magnitude

local RayCast = Ray.new(Origin.Position, Origin.CFrame.LookVector * Num)
local Part, HitPos = workspace:FindPartOnRayWithIgnoreList(RayCast, {Character, Camera:FindFirstChildOfClass("Model")})
	if Part then
		if Part.Transparency ~= 1 then
			local Distance = (Muzzle.Position - HitPos).Magnitude
			CollideOffset = CFrame.new(0,0,Distance)
		end
	else
		CollideOffset = CollideOffset:Lerp(CFrame.new(0, 0, 0), 0.1)
	end

Gray part is HRP (Viewmodel.PrimaryPart), Pink part is MUZZLE

2 Likes

I am not sure of the problem, to me it just looks like the loop is not running fast enough. Define local Origin = Viewmodel.PrimaryPart local Muzzle = Viewmodel:WaitForChild("MUZZLE") outside of the loop, especially because you are using :WaitForChild() which would be very slow to run every frame. Also, you could probably use BlockCasting instead of :FindPartOnRayWithIgnoreList() (it has been deprecated). An example of this could be

local RunService = game:GetService("RunService")
local Origin = Viewmodel.PrimaryPart
local Muzzle = Viewmodel:WaitForChild("MUZZLE")

RunService.RenderStepped:Connect(function()
	Viewmodel.PrimaryPart.CFrame = Camera.CFrame * CollideOffset

	local Direction = Origin.Position - Muzzle.Position

	local Parameters = RaycastParams.new()
	Parameters.FilterType = Enum.RaycastFilterType.Exclude
	Parameters.FilterDescendantsInstances = {Character, Camera:FindFirstChildOfClass("Model")}

	local BlockCastResult = workspace:Blockcast(Muzzle.CFrame, Muzzle.Size, Direction, Parameters)
	if BlockCastResult then
		if BlockCastResult.Transparency ~= 1 then
			local Distance = (Muzzle.Position - BlockCastResult.Position).Magnitude
			CollideOffset = CFrame.new(0, 0, Distance)
		end
	else
		CollideOffset = CollideOffset:Lerp(CFrame.new(0, 0, 0), 0.1)
	end
end)

Because I don’t have access to your viewmodel, I cannot confirm if this code will work, however I hope it points you in the right direction.

1 Like

After some hours, i got something that looks exactly like i wanted to…

I used BlockCast Instead of FindPartOnRayWithIgnoreList()
…Instead of using Origin as HRP, i added a new part called Detector :


(Orange part is Detector, Pink part is Muzzle)

…and changed code :

local Direction = Muzzle.Position - Detector.Position

local Parameters = RaycastParams.new()
Parameters.FilterType = Enum.RaycastFilterType.Exclude
Parameters.FilterDescendantsInstances = {Character, Camera:FindFirstChildOfClass("Model")}

local BlockCastResult = workspace:Blockcast(Detector.CFrame, Detector.Size * 2, Direction, Parameters)

if BlockCastResult then
   Direction = (Muzzle.Position - Detector.Position) * 1.5
   		
   local Distance = (Muzzle.Position - BlockCastResult.Position).Magnitude
   CollideOffset = CollideOffset:Lerp(CollideOffset * CFrame.new(0, 0, Distance), 0.3)
else	
   Direction = Muzzle.Position - Detector.Position
   CollideOffset = CollideOffset:Lerp(CFrame.new(0, 0, 0), 0.1)
end

But there’s one problem left… :

As you can see, for some reason viewmodel is trying to lerp to CFrame.new(0,0,0)
(i guess it happens because of when viewmodel moving from wall, blockcast stops seeing wall and viewmodel is trying to lerp)…

What should i do?