I am currently building a survival game with tools to break resources and to fight enemies. I wanted the game to be in first person so I have viewmodel system in place to make it look better. However, when I use the viewmodel, the tools seem to not be able to break resources but still work fine. I want tools to be able to detect collision with resources and be able to break them. I have a feeling that the collision doesn’t work because the viewmodel is affecting character’s actual arms and is only client side. Does anyone know why my current system isn’t working and any possible solutions?
Currently my tools (axe, pickaxe, sword) use the .touched function to detect touching.
Resources use the humanoid object to keep track of health.
My viewmodel is only client based and still uses the character arms. It comes from this video:
View Model Part 2 (there is also a part 1 which explains how it works)
-video showing why it doesn’t work-
-Tool code-
-- local tool = script.Parent
local handle = tool.Handle
local hitbox = tool.HitBox
local ProxPrompt = hitbox.ToolPickup
local settingsfolder = tool.Settings
local damageVal = settingsfolder.Damage
local cooldownVal = settingsfolder.Cooldown
local db = false
local canhit = false
local function swingFunc()
if not db then
db = true
canhit = true
local Anim = Instance.new("StringValue")
Anim.Name = "toolanim"
Anim.Value = "Slash"
Anim.Parent = tool
task.wait(0.5)
canhit = false
task.wait(cooldownVal.Value)
Anim:Destroy()
db = false
canhit = false
end
end
local function EnemyHitFunc(hitpart)
if canhit and hitpart.parent ~= tool.Parent then
if hitpart.parent ~= tool.Parent and hitpart.parent:FindFirstChild("Humanoid") and hitpart.parent:FindFirstChild("EnemyTag") then
local humanoid = hitpart.parent:FindFirstChild("Humanoid")
humanoid.Health -= damageVal.Value
canhit = false
end
end
end
local function TreeHitFunc(hitpart)
if canhit and hitpart.parent ~= tool.Parent then
if hitpart.parent ~= tool.Parent and hitpart.parent:FindFirstChild("Humanoid") and hitpart.parent:FindFirstChild("TreeTag") then
local humanoid = hitpart.parent:FindFirstChild("Humanoid")
humanoid.Health -= damageVal.Value
canhit = false
end
end
end
local function RockHitFunc(hitpart)
if canhit and hitpart.parent ~= tool.Parent then
if hitpart.parent ~= tool.Parent and hitpart.parent:FindFirstChild("Humanoid") and hitpart.parent:FindFirstChild("RockTag") then
canhit = false
local humanoid = hitpart.parent:FindFirstChild("Humanoid")
humanoid.Health -= damageVal.Value
end
end
end
tool.Activated:Connect(swingFunc)
hitbox.Touched:Connect(EnemyHitFunc)
hitbox.Touched:Connect(TreeHitFunc)
--hitbox.Touched:Connect(RockHitFunc)
while task.wait() do
if tool.Parent:FindFirstChild("Humanoid") then
hitbox.CanCollide = false
ProxPrompt.Enabled = false
else
hitbox.CanCollide = true
ProxPrompt.Enabled = true
end
end
-Viewmodel code-
-- local runMult = 10
local walkMult = 4
local swaySpeed = .1 -- 0 is fast 1 is slow
local returnSpeed = .1-- 0 is fast 1 is slow
local smoothingMult = 1-- 0 is fast 1 is slow
-----------------
local OFFSET = 0 -- the forward offset
local X = 0 -- the forward offset
local Y = 0 -- the forward offset
local runService = game:GetService("RunService")
local character = script.Parent
local VM = game.ReplicatedStorage.Viewmodel:Clone()
VM.Parent = workspace.CurrentCamera
local leftShoulder = character.Torso["Left Shoulder"]
local rightShoulder = character.Torso["Right Shoulder"]
local sine = 0
function getCFrame(cframe)
local sx, sy, sz, m00, m01, m02, m10, m11, m12, m20, m21, m22 = cframe:GetComponents()
local X = math.atan2(-m12, m22)
local Y = math.asin(m02)
local Z = math.atan2(-m01, m00)
return X,Y,Z
end
runService.RenderStepped:Connect(function(deltatime)
--character:FindFirstChild("Right Arm").LocalTransparencyModifier = 0
OFFSET = script.OFFSET.Value
X = script.X.Value
Y = script.Y.Value
--character:FindFirstChild("Left Arm").LocalTransparencyModifier = 0
local pcframe = workspace.CurrentCamera.CFrame + workspace.CurrentCamera.CFrame.LookVector * OFFSET + workspace.CurrentCamera.CFrame.RightVector * X + workspace.CurrentCamera.CFrame.UpVector * Y
local lerpedRot = VM.PrimaryPart.CFrame:lerp(pcframe,smoothingMult)
local _,_,_,m11,m12,m13,m21,m22,m23,m31,m32,m33 = lerpedRot:components();
local ogPos = pcframe.p;
local newCf = CFrame.new(ogPos.x,ogPos.y,ogPos.z,m11,m12,m13,m21,m22,m23,m31,m32,m33)
VM.PrimaryPart.CFrame = newCf;
local dist = (workspace.CurrentCamera.CFrame.Position - character.Head.Position).Magnitude
if dist < 1 then
rightShoulder.Part0 = VM.Torso
leftShoulder.Part0 = VM.Torso
else
rightShoulder.Part0 = character.Torso
leftShoulder.Part0 = character.Torso
end
end)
local val = 0
local moving = false
while task.wait() do
sine = math.sin(val)
if character.Humanoid.MoveDirection ~= Vector3.new(0,0,0) then
val += .08
game.TweenService:Create(script.X, TweenInfo.new(swaySpeed,Enum.EasingStyle.Linear,Enum.EasingDirection.Out), {Value = sine/runMult}):Play()
if sine < 0 then
game.TweenService:Create(script.Y, TweenInfo.new(swaySpeed,Enum.EasingStyle.Linear,Enum.EasingDirection.Out), {Value = -sine/runMult}):Play()
else
game.TweenService:Create(script.Y, TweenInfo.new(swaySpeed,Enum.EasingStyle.Linear,Enum.EasingDirection.Out), {Value = sine/runMult}):Play()
end
--[[
if character.Sprint.Sprinting.Value == false then
val += .1
game.TweenService:Create(script.X, TweenInfo.new(swaySpeed,Enum.EasingStyle.Linear,Enum.EasingDirection.Out), {Value = sine/runMult}):Play()
if sine < 0 then
game.TweenService:Create(script.Y, TweenInfo.new(swaySpeed,Enum.EasingStyle.Linear,Enum.EasingDirection.Out), {Value = -sine/runMult}):Play()
else
game.TweenService:Create(script.Y, TweenInfo.new(swaySpeed,Enum.EasingStyle.Linear,Enum.EasingDirection.Out), {Value = sine/runMult}):Play()
end
else
val += .2
game.TweenService:Create(script.X, TweenInfo.new(swaySpeed,Enum.EasingStyle.Linear,Enum.EasingDirection.Out), {Value = sine/walkMult}):Play()
if sine < 0 then
game.TweenService:Create(script.Y, TweenInfo.new(swaySpeed,Enum.EasingStyle.Linear,Enum.EasingDirection.Out), {Value = -sine/walkMult}):Play()
else
game.TweenService:Create(script.Y, TweenInfo.new(swaySpeed,Enum.EasingStyle.Linear,Enum.EasingDirection.Out), {Value = sine/walkMult}):Play()
end
end
]]
else
game.TweenService:Create(script.Y, TweenInfo.new(returnSpeed,Enum.EasingStyle.Linear,Enum.EasingDirection.Out), {Value = 0}):Play()
game.TweenService:Create(script.X, TweenInfo.new(returnSpeed,Enum.EasingStyle.Linear,Enum.EasingDirection.Out), {Value = 0}):Play()
end
end
-tree object in game-
-tool object in game-
If you you need more information let me know.