根据提供的code differences信息,由于没有具体的代码变更内容,我将生成一个通用的commit message模板:
``` docs(readme): 更新文档说明 - 添加项目使用指南 - 完善API接口说明 - 修正错误的配置示例 ``` 注意:由于您提供的code differences部分为空,以上是一个示例模板。当您有具体的代码变更时,请提供详细的变更内容以便生成更准确的commit message。
No files matched your search
|
Before Width: | Height: | Size: 4.9 MiB |
@@ -19,9 +19,9 @@ AnimatorOverrideController:
|
||||
type: 3}
|
||||
- m_OriginalClip: {fileID: -203655887218126122, guid: 5072af719b9b1401787c6c55f048d8ed,
|
||||
type: 3}
|
||||
m_OverrideClip: {fileID: -203655887218126122, guid: d40daebbc0e47416099e97edbbbeac04,
|
||||
m_OverrideClip: {fileID: -203655887218126122, guid: 3d031ad534e512e45bb7fe10237e6286,
|
||||
type: 3}
|
||||
- m_OriginalClip: {fileID: -203655887218126122, guid: b315bce378aec4abbac5e4070f47b069,
|
||||
type: 3}
|
||||
m_OverrideClip: {fileID: -203655887218126122, guid: 43b8e945a41aa4eb7a6ebc2cde2cf887,
|
||||
m_OverrideClip: {fileID: -203655887218126122, guid: 65518d3e21c8c4243979759cd24108d7,
|
||||
type: 3}
|
||||
@@ -66,7 +66,7 @@ ModelImporter:
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events:
|
||||
- time: 0.54800594
|
||||
- time: 0.2774049
|
||||
functionName: OnAttackEffect
|
||||
data:
|
||||
objectReferenceParameter: {instanceID: 0}
|
||||
@@ -410,128 +410,128 @@ ModelImporter:
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
- name: mixamorig:Hips
|
||||
parentName: "\u72FC\u4EBA\u653B\u51FB(Clone)"
|
||||
position: {x: 0.000006190017, y: 0.009258306, z: 0.000010177484}
|
||||
position: {x: 0.0006190017, y: 0.92583054, z: 0.0010177484}
|
||||
rotation: {x: 1.8189897e-10, y: -8.613506e-20, z: -4.735324e-10, w: 1}
|
||||
scale: {x: 1, y: 1, z: 0.99999994}
|
||||
- name: mixamorig:LeftUpLeg
|
||||
parentName: mixamorig:Hips
|
||||
position: {x: -0.001580724, y: -0.0006625086, z: 0.00006822136}
|
||||
position: {x: -0.1580724, y: -0.06625086, z: 0.0068221358}
|
||||
rotation: {x: 0.002323065, y: -0.053081393, z: 0.99763256, w: 0.043660242}
|
||||
scale: {x: 1.0000002, y: 1.0000002, z: 1}
|
||||
- name: mixamorig:LeftLeg
|
||||
parentName: mixamorig:LeftUpLeg
|
||||
position: {x: -0, y: 0.0042308737, z: 0}
|
||||
position: {x: -0, y: 0.42308736, z: 0}
|
||||
rotation: {x: -0.029839756, y: 0.0006429597, z: -0.021532256, w: 0.99932253}
|
||||
scale: {x: 1.0000005, y: 1.0000002, z: 1.0000004}
|
||||
- name: mixamorig:LeftFoot
|
||||
parentName: mixamorig:LeftLeg
|
||||
position: {x: -0, y: 0.0029479251, z: 6.9388944e-20}
|
||||
position: {x: -0, y: 0.2947925, z: 6.938895e-18}
|
||||
rotation: {x: 0.54529315, y: 0.112672314, z: -0.0742639, w: 0.82731205}
|
||||
scale: {x: 1.000001, y: 1.0000005, z: 1.0000006}
|
||||
- name: mixamorig:LeftToeBase
|
||||
parentName: mixamorig:LeftFoot
|
||||
position: {x: -2.7755578e-19, y: 0.0025459952, z: -2.7755578e-19}
|
||||
position: {x: -2.775558e-17, y: 0.2545995, z: -2.775558e-17}
|
||||
rotation: {x: 0.24118778, y: 0.014663992, z: -0.0036448347, w: 0.9703608}
|
||||
scale: {x: 0.9999996, y: 0.99999994, z: 0.9999997}
|
||||
- name: mixamorig:LeftToe_End
|
||||
parentName: mixamorig:LeftToeBase
|
||||
position: {x: -0, y: 0.0010464414, z: 0}
|
||||
position: {x: -0, y: 0.104644135, z: 0}
|
||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
- name: mixamorig:RightUpLeg
|
||||
parentName: mixamorig:Hips
|
||||
position: {x: 0.001580724, y: -0.0006625086, z: 0.000045689758}
|
||||
position: {x: 0.1580724, y: -0.06625086, z: 0.004568976}
|
||||
rotation: {x: -0.002111477, y: -0.048199356, z: 0.9978785, w: -0.043714385}
|
||||
scale: {x: 1.0000002, y: 1.0000002, z: 1.0000002}
|
||||
- name: mixamorig:RightLeg
|
||||
parentName: mixamorig:RightUpLeg
|
||||
position: {x: -0, y: 0.004226694, z: -1.04083406e-19}
|
||||
position: {x: -0, y: 0.42266938, z: -1.0408341e-17}
|
||||
rotation: {x: -0.03781653, y: -0.0008132118, z: 0.021484528, w: 0.9990534}
|
||||
scale: {x: 1.0000006, y: 1.0000004, z: 1.0000001}
|
||||
- name: mixamorig:RightFoot
|
||||
parentName: mixamorig:RightLeg
|
||||
position: {x: -0, y: 0.0029510285, z: 0}
|
||||
position: {x: -0, y: 0.29510286, z: 0}
|
||||
rotation: {x: 0.55099493, y: -0.10983675, z: 0.073447585, w: 0.8239818}
|
||||
scale: {x: 1, y: 0.99999994, z: 0.99999994}
|
||||
- name: mixamorig:RightToeBase
|
||||
parentName: mixamorig:RightFoot
|
||||
position: {x: 5.5511155e-19, y: 0.0025750154, z: -1.3877789e-19}
|
||||
position: {x: 5.551116e-17, y: 0.25750154, z: -1.387779e-17}
|
||||
rotation: {x: 0.23677067, y: -0.026426762, z: 0.0064427033, w: 0.9711848}
|
||||
scale: {x: 0.9999996, y: 0.9999997, z: 0.9999997}
|
||||
- name: mixamorig:RightToe_End
|
||||
parentName: mixamorig:RightToeBase
|
||||
position: {x: -0, y: 0.0010227846, z: -1.7347236e-20}
|
||||
position: {x: -0, y: 0.10227846, z: -1.7347237e-18}
|
||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
- name: mixamorig:Spine
|
||||
parentName: mixamorig:Hips
|
||||
position: {x: -0, y: 0.0011931198, z: -0.00016322303}
|
||||
position: {x: -0, y: 0.11931198, z: -0.016322304}
|
||||
rotation: {x: -0.06792743, y: -7.6570514e-11, z: -2.1428481e-10, w: 0.99769026}
|
||||
scale: {x: 1, y: 1, z: 1.0000001}
|
||||
- name: mixamorig:Spine1
|
||||
parentName: mixamorig:Spine
|
||||
position: {x: -0, y: 0.0014049385, z: 0}
|
||||
position: {x: -0, y: 0.14049385, z: 0}
|
||||
rotation: {x: -0.00000010430813, y: -3.0716246e-10, z: 0.0000000010710126, w: 1}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
- name: mixamorig:Spine2
|
||||
parentName: mixamorig:Spine1
|
||||
position: {x: -0, y: 0.0016056426, z: 0}
|
||||
position: {x: -0, y: 0.16056426, z: 0}
|
||||
rotation: {x: 0.000000022351742, y: 0.0000000011889004, z: 0.000000001206832,
|
||||
w: 1}
|
||||
scale: {x: 0.99999994, y: 1.0000001, z: 1.0000001}
|
||||
- name: mixamorig:Neck
|
||||
parentName: mixamorig:Spine2
|
||||
position: {x: -0, y: 0.0018063488, z: 2.63642e-10}
|
||||
position: {x: -0, y: 0.18063489, z: 0.0000000263642}
|
||||
rotation: {x: 0.06792751, y: -0.0000000017159403, z: -0.0000000015753894, w: 0.99769026}
|
||||
scale: {x: 1, y: 0.9999998, z: 0.9999999}
|
||||
- name: mixamorig:Head
|
||||
parentName: mixamorig:Neck
|
||||
position: {x: -0, y: 0.001452694, z: 0.00040141007}
|
||||
position: {x: -0, y: 0.1452694, z: 0.04014101}
|
||||
rotation: {x: -0.000000044703484, y: 0.0000000021827875, z: 7.2759593e-10, w: 1}
|
||||
scale: {x: 1, y: 1.0000001, z: 1}
|
||||
- name: mixamorig:HeadTop_End
|
||||
parentName: mixamorig:Head
|
||||
position: {x: -0, y: 0.0036708983, z: 0.0010143471}
|
||||
position: {x: -0, y: 0.36708984, z: 0.10143471}
|
||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
- name: mixamorig:LeftShoulder
|
||||
parentName: mixamorig:Spine2
|
||||
position: {x: -0.0008593107, y: 0.0015329275, z: -0.000043069263}
|
||||
position: {x: -0.08593107, y: 0.15329275, z: -0.0043069264}
|
||||
rotation: {x: 0.55490446, y: -0.42961565, z: 0.5831107, w: 0.4092596}
|
||||
scale: {x: 1.0000001, y: 1.0000001, z: 1.0000002}
|
||||
- name: mixamorig:LeftArm
|
||||
parentName: mixamorig:LeftShoulder
|
||||
position: {x: 2.7755578e-19, y: 0.0017839916, z: -2.2204462e-18}
|
||||
position: {x: 2.775558e-17, y: 0.17839916, z: -2.2204463e-16}
|
||||
rotation: {x: -0.13368575, y: -0.07338428, z: -0.012510804, w: 0.98822385}
|
||||
scale: {x: 1.0000001, y: 1.0000004, z: 1.0000004}
|
||||
- name: mixamorig:LeftForeArm
|
||||
parentName: mixamorig:LeftArm
|
||||
position: {x: -0, y: 0.0038187266, z: 0}
|
||||
position: {x: -0, y: 0.38187265, z: 0}
|
||||
rotation: {x: -0.006329544, y: -0.296342, z: -0.022776976, w: 0.95478934}
|
||||
scale: {x: 0.9999996, y: 1.0000007, z: 1.0000005}
|
||||
- name: mixamorig:LeftHand
|
||||
parentName: mixamorig:LeftForeArm
|
||||
position: {x: -4.1633362e-19, y: 0.0027106532, z: 0}
|
||||
position: {x: -4.1633363e-17, y: 0.27106532, z: 0}
|
||||
rotation: {x: -0, y: -0, z: -0.0000000037252899, w: 1}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
- name: mixamorig:RightShoulder
|
||||
parentName: mixamorig:Spine2
|
||||
position: {x: 0.0008593107, y: 0.001531406, z: -0.00003194854}
|
||||
position: {x: 0.08593107, y: 0.15314059, z: -0.0031948541}
|
||||
rotation: {x: -0.5590448, y: -0.42640686, z: 0.57987845, w: -0.41156673}
|
||||
scale: {x: 1.0000001, y: 1.0000001, z: 1.0000002}
|
||||
- name: mixamorig:RightArm
|
||||
parentName: mixamorig:RightShoulder
|
||||
position: {x: -0, y: 0.0017839916, z: 0}
|
||||
position: {x: -0, y: 0.17839916, z: 0}
|
||||
rotation: {x: 0.13425338, y: -0.09040197, z: -0.0030925567, w: -0.98680997}
|
||||
scale: {x: 1.0000002, y: 1.0000002, z: 1.0000006}
|
||||
- name: mixamorig:RightForeArm
|
||||
parentName: mixamorig:RightArm
|
||||
position: {x: -0, y: 0.0038192812, z: 1.1102231e-18}
|
||||
position: {x: -0, y: 0.38192812, z: 1.1102232e-16}
|
||||
rotation: {x: -0.0071950112, y: 0.2715749, z: 0.02268568, w: 0.962123}
|
||||
scale: {x: 0.99999994, y: 0.99999994, z: 0.99999994}
|
||||
- name: mixamorig:RightHand
|
||||
parentName: mixamorig:RightForeArm
|
||||
position: {x: -0, y: 0.0027215641, z: 1.1102231e-18}
|
||||
position: {x: -0, y: 0.27215642, z: 1.1102232e-16}
|
||||
rotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
namedPoseList:
|
||||
@@ -544,7 +544,7 @@ ModelImporter:
|
||||
armStretch: 0.05
|
||||
legStretch: 0.05
|
||||
feetSpacing: 0
|
||||
globalScale: 2
|
||||
globalScale: 200
|
||||
rootMotionBoneName:
|
||||
defaultPoseIndex: -1
|
||||
hasTranslationDoF: 0
|
||||
|
||||
@@ -0,0 +1,555 @@
|
||||
fileFormatVersion: 2
|
||||
guid: CX8atCL5UC6HxG8hLlhH1BbomgEeW3V4TtB1E5i8Y4neo5akoj0Ujtg=
|
||||
ModelImporter:
|
||||
serializedVersion: 22361
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
materials:
|
||||
materialImportMode: 2
|
||||
materialName: 0
|
||||
materialSearch: 1
|
||||
materialLocation: 1
|
||||
animations:
|
||||
legacyGenerateAnimations: 4
|
||||
bakeSimulation: 0
|
||||
resampleCurves: 1
|
||||
optimizeGameObjects: 0
|
||||
removeConstantScaleCurves: 0
|
||||
motionNodeName:
|
||||
rigImportErrors:
|
||||
rigImportWarnings:
|
||||
animationImportErrors:
|
||||
animationImportWarnings:
|
||||
animationRetargetingWarnings:
|
||||
animationDoRetargetingWarnings: 0
|
||||
importAnimatedCustomProperties: 0
|
||||
importConstraints: 0
|
||||
animationCompression: 3
|
||||
aCLCompressionLevel: 3
|
||||
aCLCurvePrecision: 0.01
|
||||
aCLFastSampleMode: 1
|
||||
animationRotationError: 0.5
|
||||
animationPositionError: 0.5
|
||||
animationScaleError: 0.5
|
||||
animationWrapMode: 0
|
||||
extraExposedTransformPaths: []
|
||||
extraUserProperties: []
|
||||
clipAnimations:
|
||||
- serializedVersion: 18
|
||||
name: "\u6280\u80FD\u7838\u5730"
|
||||
takeName: mixamo.com
|
||||
internalID: -203655887218126122
|
||||
firstFrame: 0
|
||||
lastFrame: 68
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
lockToRoot: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events:
|
||||
- time: 0.63982105
|
||||
functionName: OnSkillHit1
|
||||
data:
|
||||
objectReferenceParameter: {instanceID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
intervals: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
additiveType: 0
|
||||
basePoseType: 0
|
||||
additiveSelectedAnimation: {instanceID: 0}
|
||||
additiveSelectedAnimationFrameIndex: 0
|
||||
isReadable: 0
|
||||
tuanjieGIEnable: 0
|
||||
tuanjieGIGenSDFFactor: 1
|
||||
tuanjieGIGenSDFBias: 0.25
|
||||
tuanjieGIDoubleSidedMode: 0
|
||||
tuanjieGIGenFacetNums: 12
|
||||
meshes:
|
||||
lODScreenPercentages: []
|
||||
globalScale: 1
|
||||
meshCompression: 0
|
||||
totalVerticesCount: 0
|
||||
totalTrianglesCount: 0
|
||||
addColliders: 0
|
||||
useSRGBMaterialColor: 1
|
||||
sortHierarchyByName: 1
|
||||
importPhysicalCameras: 1
|
||||
importVisibility: 1
|
||||
importBlendShapes: 1
|
||||
importCameras: 1
|
||||
importLights: 1
|
||||
nodeNameCollisionStrategy: 1
|
||||
fileIdsGeneration: 2
|
||||
swapUVChannels: 0
|
||||
generateSecondaryUV: 0
|
||||
useFileUnits: 1
|
||||
keepQuads: 0
|
||||
weldVertices: 1
|
||||
bakeAxisConversion: 0
|
||||
preserveHierarchy: 0
|
||||
skinWeightsMode: 0
|
||||
maxBonesPerVertex: 4
|
||||
minBoneWeight: 0.001
|
||||
optimizeBones: 1
|
||||
meshOptimizationFlags: -1
|
||||
indexFormat: 0
|
||||
secondaryUVAngleDistortion: 8
|
||||
secondaryUVAreaDistortion: 15.000001
|
||||
secondaryUVHardAngle: 88
|
||||
secondaryUVMarginMethod: 1
|
||||
secondaryUVMinLightmapResolution: 40
|
||||
secondaryUVMinObjectScale: 1
|
||||
secondaryUVPackMargin: 4
|
||||
useFileScale: 1
|
||||
strictVertexDataChecks: 0
|
||||
virtualGeometry:
|
||||
virtualGeometry: 0
|
||||
useTransparent: 0
|
||||
setVGForeachMesh: 0
|
||||
isFirstUse: 1
|
||||
virtualGeometrySettings:
|
||||
generateGeometryBuffer: 0
|
||||
surfaceCompensation: 0
|
||||
allMeshUse: 1
|
||||
ignoreSimpleMesh: 0
|
||||
transformScaleState: 0
|
||||
isPossibleOverflow: 0
|
||||
hasBoneData: 0
|
||||
isBoneCountOverflow: 0
|
||||
virtualGeometryPlatformSettings:
|
||||
- serializedVersion: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
buildTarget: DefaultVirtualGeometryPlatform
|
||||
positionPrecision: -2147483648
|
||||
normalPrecision: -2147483648
|
||||
tangentPrecision: -2147483648
|
||||
boneWeightPrecision: -2147483648
|
||||
detailedTriangleCount: 0
|
||||
detailedVertexCount: 0
|
||||
rootPageSize: 0
|
||||
streamablePageSize: 0
|
||||
reserveTrianglePercent: 100
|
||||
reserveDetailLevel: 0
|
||||
- serializedVersion: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
buildTarget: Standalone
|
||||
positionPrecision: -2147483648
|
||||
normalPrecision: -2147483648
|
||||
tangentPrecision: -2147483648
|
||||
boneWeightPrecision: -2147483648
|
||||
detailedTriangleCount: 0
|
||||
detailedVertexCount: 0
|
||||
rootPageSize: 0
|
||||
streamablePageSize: 0
|
||||
reserveTrianglePercent: 100
|
||||
reserveDetailLevel: 0
|
||||
- serializedVersion: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
buildTarget: iPhone
|
||||
positionPrecision: -2147483648
|
||||
normalPrecision: -2147483648
|
||||
tangentPrecision: -2147483648
|
||||
boneWeightPrecision: -2147483648
|
||||
detailedTriangleCount: 0
|
||||
detailedVertexCount: 0
|
||||
rootPageSize: 0
|
||||
streamablePageSize: 0
|
||||
reserveTrianglePercent: 100
|
||||
reserveDetailLevel: 0
|
||||
- serializedVersion: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
buildTarget: Android
|
||||
positionPrecision: -2147483648
|
||||
normalPrecision: -2147483648
|
||||
tangentPrecision: -2147483648
|
||||
boneWeightPrecision: -2147483648
|
||||
detailedTriangleCount: 0
|
||||
detailedVertexCount: 0
|
||||
rootPageSize: 0
|
||||
streamablePageSize: 0
|
||||
reserveTrianglePercent: 100
|
||||
reserveDetailLevel: 0
|
||||
selectedVGMeshes: []
|
||||
supportVGMeshes: []
|
||||
tangentSpace:
|
||||
normalSmoothAngle: 60
|
||||
normalImportMode: 0
|
||||
tangentImportMode: 3
|
||||
normalCalculationMode: 4
|
||||
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
|
||||
blendShapeNormalImportMode: 1
|
||||
normalSmoothingSource: 0
|
||||
referencedClips: []
|
||||
importAnimation: 1
|
||||
overrideDefaultPose: 0
|
||||
humanDescription:
|
||||
serializedVersion: 3
|
||||
human:
|
||||
- boneName: mixamorig:Hips
|
||||
humanName: Hips
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:LeftUpLeg
|
||||
humanName: LeftUpperLeg
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:RightUpLeg
|
||||
humanName: RightUpperLeg
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:LeftLeg
|
||||
humanName: LeftLowerLeg
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:RightLeg
|
||||
humanName: RightLowerLeg
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:LeftFoot
|
||||
humanName: LeftFoot
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:RightFoot
|
||||
humanName: RightFoot
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:Spine
|
||||
humanName: Spine
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:Spine1
|
||||
humanName: Chest
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:Neck
|
||||
humanName: Neck
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:Head
|
||||
humanName: Head
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:LeftShoulder
|
||||
humanName: LeftShoulder
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:RightShoulder
|
||||
humanName: RightShoulder
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:LeftArm
|
||||
humanName: LeftUpperArm
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:RightArm
|
||||
humanName: RightUpperArm
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:LeftForeArm
|
||||
humanName: LeftLowerArm
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:RightForeArm
|
||||
humanName: RightLowerArm
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:LeftHand
|
||||
humanName: LeftHand
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:RightHand
|
||||
humanName: RightHand
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:LeftToeBase
|
||||
humanName: LeftToes
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:RightToeBase
|
||||
humanName: RightToes
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: mixamorig:Spine2
|
||||
humanName: UpperChest
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
max: {x: 0, y: 0, z: 0}
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
skeleton:
|
||||
- name: "\u77F3\u5DE8\u4EBA\u653B\u51FB(Clone)"
|
||||
parentName:
|
||||
position: {x: 0, y: 0, z: 0}
|
||||
rotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
- name: node_0
|
||||
parentName: "\u77F3\u5DE8\u4EBA\u653B\u51FB(Clone)"
|
||||
position: {x: -0, y: 0, z: 0}
|
||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
- name: mixamorig:Hips
|
||||
parentName: "\u77F3\u5DE8\u4EBA\u653B\u51FB(Clone)"
|
||||
position: {x: 0.000025028497, y: 0.0054313573, z: -0.0000036996557}
|
||||
rotation: {x: 0.0000000010470055, y: 0.000000016171759, z: 0.0000000073942017,
|
||||
w: 1}
|
||||
scale: {x: 0.9999999, y: 1, z: 1}
|
||||
- name: mixamorig:Spine
|
||||
parentName: mixamorig:Hips
|
||||
position: {x: -0, y: 0.0007356823, z: -0.00006496691}
|
||||
rotation: {x: -0.04402572, y: -0.000000013245289, z: -0.00000001143321, w: 0.9990304}
|
||||
scale: {x: 0.99999994, y: 1.0000001, z: 0.99999994}
|
||||
- name: mixamorig:Spine1
|
||||
parentName: mixamorig:Spine
|
||||
position: {x: -0, y: 0.00086163584, z: 0}
|
||||
rotation: {x: -0.0000000037252903, y: -0.000000005867169, z: 0.0000000012216193,
|
||||
w: 1}
|
||||
scale: {x: 0.99999994, y: 1, z: 0.9999998}
|
||||
- name: mixamorig:Spine2
|
||||
parentName: mixamorig:Spine1
|
||||
position: {x: -0, y: 0.0009847267, z: 6.9388944e-20}
|
||||
rotation: {x: 0.000000011175871, y: 0.00000000190893, z: 0.000000012783833,
|
||||
w: 1}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
- name: mixamorig:LeftShoulder
|
||||
parentName: mixamorig:Spine2
|
||||
position: {x: -0.00058580056, y: 0.00092829805, z: -0.000014055445}
|
||||
rotation: {x: 0.56822485, y: -0.4168453, z: 0.5826243, w: 0.40485722}
|
||||
scale: {x: 1, y: 1, z: 0.9999998}
|
||||
- name: mixamorig:LeftArm
|
||||
parentName: mixamorig:LeftShoulder
|
||||
position: {x: -0, y: 0.0012267674, z: 0}
|
||||
rotation: {x: -0.1461725, y: -0.06026239, z: -0.004887014, w: 0.98740983}
|
||||
scale: {x: 1, y: 1.0000005, z: 1.0000006}
|
||||
- name: mixamorig:LeftForeArm
|
||||
parentName: mixamorig:LeftArm
|
||||
position: {x: 1.3877789e-19, y: 0.0020718891, z: -1.1102231e-18}
|
||||
rotation: {x: -0.0025324821, y: -0.01076787, z: -0.02900415, w: 0.9995181}
|
||||
scale: {x: 1.0000005, y: 1.0000001, z: 1.0000007}
|
||||
- name: mixamorig:LeftHand
|
||||
parentName: mixamorig:LeftForeArm
|
||||
position: {x: -1.3877789e-19, y: 0.0023369573, z: 0}
|
||||
rotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
- name: mixamorig:RightShoulder
|
||||
parentName: mixamorig:Spine2
|
||||
position: {x: 0.00058580056, y: 0.000928613, z: -0.00001762298}
|
||||
rotation: {x: -0.5662846, y: -0.41832346, z: 0.5842823, w: -0.40366006}
|
||||
scale: {x: 1.0000002, y: 1.0000002, z: 1.0000001}
|
||||
- name: mixamorig:RightArm
|
||||
parentName: mixamorig:RightShoulder
|
||||
position: {x: -1.3877789e-19, y: 0.0012267674, z: 1.1102231e-18}
|
||||
rotation: {x: -0.14613014, y: 0.04451628, z: 0.0058504045, w: 0.988246}
|
||||
scale: {x: 1.0000001, y: 1, z: 1}
|
||||
- name: mixamorig:RightForeArm
|
||||
parentName: mixamorig:RightArm
|
||||
position: {x: 6.9388944e-20, y: 0.0020716428, z: 0}
|
||||
rotation: {x: 0.0006950349, y: -0.010786076, z: -0.028526084, w: -0.9995346}
|
||||
scale: {x: 1, y: 1.0000002, z: 1}
|
||||
- name: mixamorig:RightHand
|
||||
parentName: mixamorig:RightForeArm
|
||||
position: {x: -0, y: 0.0023326648, z: 0}
|
||||
rotation: {x: -0.0000000074505797, y: 9.3132246e-10, z: 0.000000007217749, w: 1}
|
||||
scale: {x: 1.0000004, y: 1.0000002, z: 1.0000001}
|
||||
- name: mixamorig:Neck
|
||||
parentName: mixamorig:Spine2
|
||||
position: {x: -0, y: 0.0011078174, z: -3.276992e-11}
|
||||
rotation: {x: -0.01486942, y: 3.426908e-10, z: 0.0000000057881673, w: 0.9998895}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
- name: mixamorig:Head
|
||||
parentName: mixamorig:Neck
|
||||
position: {x: -0, y: 0.0001232034, z: 0.000086430045}
|
||||
rotation: {x: 0.0000000037252903, y: -0.000000004246088, z: -0.00000001824041,
|
||||
w: 1}
|
||||
scale: {x: 1.0000001, y: 1, z: 1}
|
||||
- name: mixamorig:HeadTop_End
|
||||
parentName: mixamorig:Head
|
||||
position: {x: -0, y: 0.0014060154, z: 0.0009863526}
|
||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
- name: mixamorig:RightUpLeg
|
||||
parentName: mixamorig:Hips
|
||||
position: {x: 0.00093557435, y: -0.0004081661, z: -0.000011268007}
|
||||
rotation: {x: 0.0051710024, y: 0.055403285, z: 0.99413, w: -0.09278605}
|
||||
scale: {x: 0.9999997, y: 0.99999976, z: 1}
|
||||
- name: mixamorig:RightLeg
|
||||
parentName: mixamorig:RightUpLeg
|
||||
position: {x: -0, y: 0.0022295937, z: 0}
|
||||
rotation: {x: -0.19639736, y: 0.010663452, z: -0.05315652, w: 0.9790244}
|
||||
scale: {x: 1.0000004, y: 1.000001, z: 1.0000004}
|
||||
- name: mixamorig:RightFoot
|
||||
parentName: mixamorig:RightLeg
|
||||
position: {x: -0, y: 0.001674451, z: -1.3877789e-19}
|
||||
rotation: {x: 0.5388422, y: 0.049867895, z: -0.03197695, w: 0.84032124}
|
||||
scale: {x: 1.0000004, y: 1.0000005, z: 1.0000002}
|
||||
- name: mixamorig:RightToeBase
|
||||
parentName: mixamorig:RightFoot
|
||||
position: {x: -0, y: 0.0016622617, z: 1.3877789e-19}
|
||||
rotation: {x: 0.35963094, y: -0.010496464, z: 0.0040457686, w: 0.93302685}
|
||||
scale: {x: 1.0000002, y: 1.0000001, z: 1.0000002}
|
||||
- name: mixamorig:RightToe_End
|
||||
parentName: mixamorig:RightToeBase
|
||||
position: {x: -0, y: 0.00075564603, z: -4.336809e-21}
|
||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
- name: mixamorig:LeftUpLeg
|
||||
parentName: mixamorig:Hips
|
||||
position: {x: -0.00093557435, y: -0.0004081661, z: 0.0000016435517}
|
||||
rotation: {x: -0.00520432, y: 0.0557641, z: 0.9941105, w: 0.09277684}
|
||||
scale: {x: 1.0000001, y: 0.9999999, z: 0.99999994}
|
||||
- name: mixamorig:LeftLeg
|
||||
parentName: mixamorig:LeftUpLeg
|
||||
position: {x: -2.7755578e-19, y: 0.0022297692, z: 0}
|
||||
rotation: {x: -0.20584376, y: 0.12434317, z: 0.026378915, w: 0.9702944}
|
||||
scale: {x: 1, y: 1.0000004, z: 0.9999998}
|
||||
- name: mixamorig:LeftFoot
|
||||
parentName: mixamorig:LeftLeg
|
||||
position: {x: -0, y: 0.001677993, z: 1.7347238e-19}
|
||||
rotation: {x: 0.52844125, y: -0.16615163, z: 0.10633126, w: 0.8257344}
|
||||
scale: {x: 1.0000006, y: 1.0000005, z: 0.99999976}
|
||||
- name: mixamorig:LeftToeBase
|
||||
parentName: mixamorig:LeftFoot
|
||||
position: {x: -0, y: 0.0016452173, z: -2.0816683e-19}
|
||||
rotation: {x: 0.36363024, y: 0.012258099, z: -0.0047854558, w: 0.9314505}
|
||||
scale: {x: 0.9999995, y: 0.99999976, z: 0.9999999}
|
||||
- name: mixamorig:LeftToe_End
|
||||
parentName: mixamorig:LeftToeBase
|
||||
position: {x: -2.7755578e-19, y: 0.00077092234, z: 8.673618e-21}
|
||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
namedPoseList:
|
||||
- name: Default
|
||||
skeleton: []
|
||||
armTwist: 0.5
|
||||
foreArmTwist: 0.5
|
||||
upperLegTwist: 0.5
|
||||
legTwist: 0.5
|
||||
armStretch: 0.05
|
||||
legStretch: 0.05
|
||||
feetSpacing: 0
|
||||
globalScale: 1
|
||||
rootMotionBoneName:
|
||||
defaultPoseIndex: -1
|
||||
hasTranslationDoF: 0
|
||||
hasExtraRoot: 1
|
||||
skeletonHasParents: 1
|
||||
lastHumanDescriptionAvatarSource: {fileID: 9000000, guid: d40daebbc0e47416099e97edbbbeac04,
|
||||
type: 3}
|
||||
autoGenerateAvatarMappingIfUnspecified: 1
|
||||
animationType: 3
|
||||
humanoidOversampling: 1
|
||||
avatarSetup: 2
|
||||
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
|
||||
importBlendShapeDeformPercent: 1
|
||||
remapMaterialsIfMaterialImportModeIsNone: 0
|
||||
additionalBone: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: Xn9Nt3upASmCnjf71jScieVdxk5dt59IaBF5ly41RuZmaEtbnQfCoRA=
|
||||
guid: WyscsSisBiiG1MkL0a/b5vj9hwx7ySdmScsXfqIgXODEW8HYzrEwk7Y=
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: WnId4S6oACiY5vmJ2go0hyntRvZgo81zfwCX72sqoNOwt+8Wsvvcl0s=
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
After Width: | Height: | Size: 1.1 MiB |
@@ -0,0 +1,163 @@
|
||||
fileFormatVersion: 2
|
||||
guid: XXMetn77Wi3S8NHBfR0p60o3Ff9IjatUZVxmgVVgoDJnsMw1GWQp0aM=
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 14
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
webStreaming: 0
|
||||
priorityLevel: 0
|
||||
uploadedMode: 2
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 256
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WeixinMiniGame
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: PlayableAds
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
doOverrideTextureManagerOperations: 0
|
||||
platformOperationGroupSettings:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
After Width: | Height: | Size: 1.0 MiB |
@@ -0,0 +1,163 @@
|
||||
fileFormatVersion: 2
|
||||
guid: B3NMvSOoB34OawufXPPYrzVfNzS6hZLFn8owZWIABSJSEv7VNIXw5kQ=
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 14
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
webStreaming: 0
|
||||
priorityLevel: 0
|
||||
uploadedMode: 2
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 256
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WeixinMiniGame
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: PlayableAds
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
doOverrideTextureManagerOperations: 0
|
||||
platformOperationGroupSettings:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
After Width: | Height: | Size: 2.4 MiB |
@@ -0,0 +1,163 @@
|
||||
fileFormatVersion: 2
|
||||
guid: WylLtCmuAC77eU9cELADoML283FqYfUq/TiO5Aq/UEdyMy9jGLkLSNw=
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 14
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
webStreaming: 0
|
||||
priorityLevel: 0
|
||||
uploadedMode: 2
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 512
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WeixinMiniGame
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: PlayableAds
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
doOverrideTextureManagerOperations: 0
|
||||
platformOperationGroupSettings:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
After Width: | Height: | Size: 2.4 MiB |
@@ -0,0 +1,163 @@
|
||||
fileFormatVersion: 2
|
||||
guid: CnJN5CqqVCriKlCAguU+7Gra9Pc8MZo5d1d6VoeGcOOvmk+pBdCzws4=
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 14
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
webStreaming: 0
|
||||
priorityLevel: 0
|
||||
uploadedMode: 2
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 512
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WeixinMiniGame
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: PlayableAds
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
doOverrideTextureManagerOperations: 0
|
||||
platformOperationGroupSettings:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
After Width: | Height: | Size: 2.4 MiB |
@@ -0,0 +1,163 @@
|
||||
fileFormatVersion: 2
|
||||
guid: DywXvCL4Wy1sPf32jIiKkm6uogJC3L0OHuBksuZy2Kxj158zAXdNxy0=
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 14
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
webStreaming: 0
|
||||
priorityLevel: 0
|
||||
uploadedMode: 2
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 512
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WeixinMiniGame
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: PlayableAds
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
doOverrideTextureManagerOperations: 0
|
||||
platformOperationGroupSettings:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
After Width: | Height: | Size: 3.1 MiB |
@@ -0,0 +1,163 @@
|
||||
fileFormatVersion: 2
|
||||
guid: WygetiilAn8XvWbtGJ4uhaSD/yrXjrxvhT/GXLPKISUkhfxMk/BUFlQ=
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 14
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
webStreaming: 0
|
||||
priorityLevel: 0
|
||||
uploadedMode: 2
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WeixinMiniGame
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: PlayableAds
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
doOverrideTextureManagerOperations: 0
|
||||
platformOperationGroupSettings:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
After Width: | Height: | Size: 2.2 MiB |
@@ -0,0 +1,163 @@
|
||||
fileFormatVersion: 2
|
||||
guid: B3IYtiOsBy30XfzNdvmYCqaBjJr0nLhulXlH/g005xRwcG+3BiMFaeA=
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 14
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
webStreaming: 0
|
||||
priorityLevel: 0
|
||||
uploadedMode: 2
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 512
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WeixinMiniGame
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: PlayableAds
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
doOverrideTextureManagerOperations: 0
|
||||
platformOperationGroupSettings:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -16,13 +16,27 @@ public class ShockwaveRing : MonoBehaviour
|
||||
private Material mat;
|
||||
private float timer = -1f;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
if (mat != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 用 .material 生成独立实例,不影响材质资产
|
||||
mat = GetComponent<Renderer>().material;
|
||||
mat.SetFloat("_Progress", 0f);
|
||||
transform.localScale = startScale;
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -30,6 +44,7 @@ public class ShockwaveRing : MonoBehaviour
|
||||
/// </summary>
|
||||
public void Play()
|
||||
{
|
||||
Initialize();
|
||||
gameObject.SetActive(true);
|
||||
timer = 0f;
|
||||
mat.SetFloat("_Progress", 0f);
|
||||
|
||||
@@ -125,7 +125,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 9faf161c1d2f649baaf36efc3fb301fc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
duration: 1
|
||||
duration: 0.2
|
||||
autoDestroy: 1
|
||||
overrideColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
overrideRadius: 0
|
||||
|
||||
@@ -385,7 +385,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
showStunIndicator: 1
|
||||
indicatorHeight: 0.35
|
||||
stunIndicatorPrefab: {fileID: 0}
|
||||
stunIndicatorPrefab: {fileID: 2432573200162841629, guid: de288ea16be0c1544a4c6eb71e899570,
|
||||
type: 3}
|
||||
--- !u!114 &3354386702202317803
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -398,8 +399,10 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: da330bbd52e2a424dbe6231c018a3c60, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
characterDataName:
|
||||
level: 1
|
||||
speed: 5
|
||||
detectionRange: 30
|
||||
detectionRange: 15
|
||||
attackRange: 1
|
||||
modelFacingOffset: 0
|
||||
attackPower: 10
|
||||
@@ -414,6 +417,7 @@ MonoBehaviour:
|
||||
summonerMode: 0
|
||||
returnToAnchorWhenIdle: 0
|
||||
anchorArrivalDistance: 0.35
|
||||
useAnchorLeash: 0
|
||||
target: {fileID: 0}
|
||||
--- !u!114 &165373885999363036
|
||||
MonoBehaviour:
|
||||
|
||||
@@ -504,7 +504,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
showStunIndicator: 1
|
||||
indicatorHeight: 0.35
|
||||
stunIndicatorPrefab: {fileID: 0}
|
||||
stunIndicatorPrefab: {fileID: 2432573200162841629, guid: de288ea16be0c1544a4c6eb71e899570,
|
||||
type: 3}
|
||||
--- !u!114 &3330526767746070308
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -522,7 +523,7 @@ MonoBehaviour:
|
||||
speed: 5
|
||||
detectionRange: 100
|
||||
attackRange: 6
|
||||
modelFacingOffset: 0
|
||||
modelFacingOffset: 90
|
||||
attackPower: 10
|
||||
attackDuration: 0
|
||||
attackType: 2
|
||||
|
||||
@@ -416,7 +416,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
showStunIndicator: 1
|
||||
indicatorHeight: 0.35
|
||||
stunIndicatorPrefab: {fileID: 0}
|
||||
stunIndicatorPrefab: {fileID: 2432573200162841629, guid: de288ea16be0c1544a4c6eb71e899570,
|
||||
type: 3}
|
||||
--- !u!114 &166917633014101340
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -420,7 +420,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
showStunIndicator: 1
|
||||
indicatorHeight: 0.35
|
||||
stunIndicatorPrefab: {fileID: 0}
|
||||
stunIndicatorPrefab: {fileID: 2432573200162841629, guid: de288ea16be0c1544a4c6eb71e899570,
|
||||
type: 3}
|
||||
--- !u!114 &7384803545623865944
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -311,7 +311,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
showStunIndicator: 1
|
||||
indicatorHeight: 0.35
|
||||
stunIndicatorPrefab: {fileID: 0}
|
||||
stunIndicatorPrefab: {fileID: 2432573200162841629, guid: de288ea16be0c1544a4c6eb71e899570,
|
||||
type: 3}
|
||||
--- !u!114 &3749684936670238626
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -346,7 +346,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
showStunIndicator: 1
|
||||
indicatorHeight: 0.35
|
||||
stunIndicatorPrefab: {fileID: 0}
|
||||
stunIndicatorPrefab: {fileID: 2432573200162841629, guid: de288ea16be0c1544a4c6eb71e899570,
|
||||
type: 3}
|
||||
--- !u!114 &233433209084818606
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -362,7 +363,7 @@ MonoBehaviour:
|
||||
characterDataName:
|
||||
level: 1
|
||||
speed: 5
|
||||
detectionRange: 30
|
||||
detectionRange: 20
|
||||
attackRange: 6
|
||||
modelFacingOffset: 90
|
||||
attackPower: 10
|
||||
@@ -378,6 +379,7 @@ MonoBehaviour:
|
||||
summonerMode: 0
|
||||
returnToAnchorWhenIdle: 0
|
||||
anchorArrivalDistance: 0.35
|
||||
useAnchorLeash: 0
|
||||
target: {fileID: 0}
|
||||
--- !u!114 &547187195648260442
|
||||
MonoBehaviour:
|
||||
|
||||
@@ -401,7 +401,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
showStunIndicator: 1
|
||||
indicatorHeight: 0.35
|
||||
stunIndicatorPrefab: {fileID: 0}
|
||||
stunIndicatorPrefab: {fileID: 2432573200162841629, guid: de288ea16be0c1544a4c6eb71e899570,
|
||||
type: 3}
|
||||
--- !u!114 &5283395080195203019
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -414,8 +415,10 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: da330bbd52e2a424dbe6231c018a3c60, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
characterDataName:
|
||||
level: 1
|
||||
speed: 5
|
||||
detectionRange: 30
|
||||
detectionRange: 20
|
||||
attackRange: 6
|
||||
modelFacingOffset: 0
|
||||
attackPower: 10
|
||||
@@ -431,6 +434,7 @@ MonoBehaviour:
|
||||
summonerMode: 0
|
||||
returnToAnchorWhenIdle: 0
|
||||
anchorArrivalDistance: 0.35
|
||||
useAnchorLeash: 0
|
||||
target: {fileID: 0}
|
||||
--- !u!114 &6342080793053654425
|
||||
MonoBehaviour:
|
||||
|
||||
@@ -343,7 +343,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
showStunIndicator: 1
|
||||
indicatorHeight: 0.35
|
||||
stunIndicatorPrefab: {fileID: 0}
|
||||
stunIndicatorPrefab: {fileID: 2432573200162841629, guid: de288ea16be0c1544a4c6eb71e899570,
|
||||
type: 3}
|
||||
--- !u!114 &3995251606272715396
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -356,10 +357,12 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: da330bbd52e2a424dbe6231c018a3c60, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
characterDataName:
|
||||
level: 1
|
||||
speed: 5
|
||||
detectionRange: 30
|
||||
attackRange: 1
|
||||
modelFacingOffset: 0
|
||||
detectionRange: 15
|
||||
attackRange: 1.5
|
||||
modelFacingOffset: 90
|
||||
attackPower: 10
|
||||
attackDuration: 0
|
||||
attackType: 0
|
||||
@@ -372,6 +375,7 @@ MonoBehaviour:
|
||||
summonerMode: 0
|
||||
returnToAnchorWhenIdle: 0
|
||||
anchorArrivalDistance: 0.35
|
||||
useAnchorLeash: 0
|
||||
target: {fileID: 0}
|
||||
--- !u!114 &7519013316474627281
|
||||
MonoBehaviour:
|
||||
|
||||
@@ -329,7 +329,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
showStunIndicator: 1
|
||||
indicatorHeight: 0.35
|
||||
stunIndicatorPrefab: {fileID: 0}
|
||||
stunIndicatorPrefab: {fileID: 2432573200162841629, guid: de288ea16be0c1544a4c6eb71e899570,
|
||||
type: 3}
|
||||
--- !u!114 &7308248179790118654
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -342,9 +343,11 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: da330bbd52e2a424dbe6231c018a3c60, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
characterDataName:
|
||||
level: 1
|
||||
speed: 5
|
||||
detectionRange: 30
|
||||
attackRange: 1
|
||||
detectionRange: 15
|
||||
attackRange: 1.5
|
||||
modelFacingOffset: 0
|
||||
attackPower: 10
|
||||
attackDuration: 0
|
||||
@@ -358,6 +361,7 @@ MonoBehaviour:
|
||||
summonerMode: 0
|
||||
returnToAnchorWhenIdle: 0
|
||||
anchorArrivalDistance: 0.35
|
||||
useAnchorLeash: 0
|
||||
target: {fileID: 0}
|
||||
--- !u!114 &5519732045501058211
|
||||
MonoBehaviour:
|
||||
@@ -374,6 +378,10 @@ MonoBehaviour:
|
||||
skillDamage: 125
|
||||
skillRadius: 2.5
|
||||
skillAnimationDuration: 2.22
|
||||
groundCrackEffectPrefab: {fileID: 1670833528851026573, guid: 066bbd566f6034806a29d1e0a6517df4,
|
||||
type: 3}
|
||||
groundCrackForwardDistance: 1.2
|
||||
groundCrackHeightOffset: 0.05
|
||||
--- !u!4 &4457840052845775698 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: 62d9f853c067ff443bd2a3aa382ab563,
|
||||
|
||||
@@ -431,7 +431,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
showStunIndicator: 1
|
||||
indicatorHeight: 0.35
|
||||
stunIndicatorPrefab: {fileID: 0}
|
||||
stunIndicatorPrefab: {fileID: 2432573200162841629, guid: de288ea16be0c1544a4c6eb71e899570,
|
||||
type: 3}
|
||||
--- !u!114 &2471575427310325278
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -444,8 +445,10 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: da330bbd52e2a424dbe6231c018a3c60, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
characterDataName:
|
||||
level: 1
|
||||
speed: 5
|
||||
detectionRange: 30
|
||||
detectionRange: 20
|
||||
attackRange: 6
|
||||
modelFacingOffset: 0
|
||||
attackPower: 10
|
||||
@@ -461,6 +464,7 @@ MonoBehaviour:
|
||||
summonerMode: 0
|
||||
returnToAnchorWhenIdle: 0
|
||||
anchorArrivalDistance: 0.35
|
||||
useAnchorLeash: 0
|
||||
target: {fileID: 0}
|
||||
--- !u!114 &3563675809045930453
|
||||
MonoBehaviour:
|
||||
|
||||
@@ -241,7 +241,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
showStunIndicator: 1
|
||||
indicatorHeight: 0.35
|
||||
stunIndicatorPrefab: {fileID: 0}
|
||||
stunIndicatorPrefab: {fileID: 2432573200162841629, guid: de288ea16be0c1544a4c6eb71e899570,
|
||||
type: 3}
|
||||
--- !u!114 &1685608640327596089
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -254,8 +255,10 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: da330bbd52e2a424dbe6231c018a3c60, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
characterDataName:
|
||||
level: 1
|
||||
speed: 5
|
||||
detectionRange: 30
|
||||
detectionRange: 15
|
||||
attackRange: 1
|
||||
modelFacingOffset: 0
|
||||
attackPower: 10
|
||||
@@ -270,6 +273,7 @@ MonoBehaviour:
|
||||
summonerMode: 0
|
||||
returnToAnchorWhenIdle: 0
|
||||
anchorArrivalDistance: 0.35
|
||||
useAnchorLeash: 0
|
||||
target: {fileID: 0}
|
||||
--- !u!114 &5070228847944057027
|
||||
MonoBehaviour:
|
||||
|
||||
@@ -268,7 +268,7 @@ MonoBehaviour:
|
||||
characterDataName:
|
||||
level: 1
|
||||
speed: 5
|
||||
detectionRange: 30
|
||||
detectionRange: 15
|
||||
attackRange: 1.5
|
||||
modelFacingOffset: 0
|
||||
attackPower: 10
|
||||
@@ -283,6 +283,7 @@ MonoBehaviour:
|
||||
summonerMode: 0
|
||||
returnToAnchorWhenIdle: 0
|
||||
anchorArrivalDistance: 0.35
|
||||
useAnchorLeash: 0
|
||||
target: {fileID: 0}
|
||||
--- !u!114 &2537748805912434613
|
||||
MonoBehaviour:
|
||||
@@ -300,7 +301,7 @@ MonoBehaviour:
|
||||
skillRadius: 2
|
||||
stunDuration: 1
|
||||
skillAnimationDuration: 0
|
||||
shockwaveEffectPrefab: {fileID: 2432573200162841629, guid: de288ea16be0c1544a4c6eb71e899570,
|
||||
shockwaveEffectPrefab: {fileID: 2197285705285267162, guid: c2264ab9308eec342a9aabba9e806a39,
|
||||
type: 3}
|
||||
--- !u!1001 &5212681125682285543
|
||||
PrefabInstance:
|
||||
|
||||
@@ -230,7 +230,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
showStunIndicator: 1
|
||||
indicatorHeight: 0.35
|
||||
stunIndicatorPrefab: {fileID: 0}
|
||||
stunIndicatorPrefab: {fileID: 2432573200162841629, guid: de288ea16be0c1544a4c6eb71e899570,
|
||||
type: 3}
|
||||
--- !u!114 &3361318073217798046
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -243,8 +244,10 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: da330bbd52e2a424dbe6231c018a3c60, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
characterDataName:
|
||||
level: 1
|
||||
speed: 5
|
||||
detectionRange: 30
|
||||
detectionRange: 15
|
||||
attackRange: 1
|
||||
modelFacingOffset: 0
|
||||
attackPower: 10
|
||||
@@ -259,6 +262,7 @@ MonoBehaviour:
|
||||
summonerMode: 0
|
||||
returnToAnchorWhenIdle: 0
|
||||
anchorArrivalDistance: 0.35
|
||||
useAnchorLeash: 0
|
||||
target: {fileID: 0}
|
||||
--- !u!114 &5891340383424048665
|
||||
MonoBehaviour:
|
||||
|
||||
@@ -9,32 +9,32 @@ MonoBehaviour:
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: faf0a0507d15947d093eb25117aac735, type: 3}
|
||||
m_Script: {fileID: 11500000, guid: 6b1505c16dbfd46b0b43df9584c2d033, type: 3}
|
||||
m_Name: HeroRoster
|
||||
m_EditorClassIdentifier:
|
||||
heroes:
|
||||
- displayName: "\u76FE\u536B"
|
||||
prefab: {fileID: 1242979668690031507, guid: 5a43e36885a204515891085639dd22c4,
|
||||
type: 3}
|
||||
icon: {fileID: 21300000, guid: edea9239670494fc69b62e2fdc8525f5, type: 3}
|
||||
isMelee: 1
|
||||
- displayName: "\u4EBA\u7C7B\u58EB\u5175"
|
||||
prefab: {fileID: 7945271050725079514, guid: 04ae1b1fe51474dda8ae5daf0b1df7c1,
|
||||
type: 3}
|
||||
icon: {fileID: 21300000, guid: 3f35fdb898d8648e0a01f5f7c6e5943c, type: 3}
|
||||
isMelee: 1
|
||||
- displayName: "\u7CBE\u9510\u58EB\u5175"
|
||||
prefab: {fileID: 3933539425749946856, guid: 6be579752d2424feea054ce267928002,
|
||||
type: 3}
|
||||
icon: {fileID: 21300000, guid: b86682305b7af4a5983b9f24110d7055, type: 3}
|
||||
isMelee: 1
|
||||
- displayName: "\u5F13\u7BAD\u624B"
|
||||
prefab: {fileID: 5200308054099318121, guid: 7d2074c48a1b3544eb534bb509ffc845,
|
||||
type: 3}
|
||||
icon: {fileID: 21300000, guid: 4e0429f3f8a3046c590d7fc5ce85c915, type: 3}
|
||||
isMelee: 0
|
||||
- displayName: "\u6CD5\u5E08"
|
||||
prefab: {fileID: 7062617501994129594, guid: 6fb249c0311f442ecb190db77248eafc,
|
||||
type: 3}
|
||||
icon: {fileID: 21300000, guid: d6b94f721183e428f9a7d708ab1c6386, type: 3}
|
||||
icon: {fileID: 0}
|
||||
isMelee: 0
|
||||
- displayName: "\u5F13\u7BAD\u624B"
|
||||
prefab: {fileID: 5200308054099318121, guid: 7d2074c48a1b3544eb534bb509ffc845,
|
||||
type: 3}
|
||||
icon: {fileID: 0}
|
||||
isMelee: 0
|
||||
- displayName: "\u76FE\u536B"
|
||||
prefab: {fileID: 1242979668690031507, guid: 5a43e36885a204515891085639dd22c4,
|
||||
type: 3}
|
||||
icon: {fileID: 0}
|
||||
isMelee: 1
|
||||
- displayName: "\u5F13\u7BAD\u730E\u4EBA"
|
||||
prefab: {fileID: 4059575966999087028, guid: 4331d3c67d9c243cf8320a3a815cd03c,
|
||||
type: 3}
|
||||
icon: {fileID: 0}
|
||||
isMelee: 0
|
||||
- displayName: "\u77F3\u5DE8\u4EBA"
|
||||
prefab: {fileID: 4471054466352856454, guid: 52e49b3af34914387b829cef0563b36e,
|
||||
type: 3}
|
||||
icon: {fileID: 0}
|
||||
isMelee: 1
|
||||
@@ -14,6 +14,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
characterId: mage
|
||||
characterName: "\u6CD5\u5E08"
|
||||
rarity: 2
|
||||
description: "\u9B54\u6CD5\u653B\u51FB\u5355\u4F4D\uFF0C\u4F24\u5BB3\u6781\u9AD8\uFF0C\u8840\u91CF\u6781\u4F4E"
|
||||
cardIcon: {fileID: 21300000, guid: d6b94f721183e428f9a7d708ab1c6386, type: 3}
|
||||
unitPrefab: {fileID: 7062617501994129594, guid: 6fb249c0311f442ecb190db77248eafc,
|
||||
|
||||
@@ -14,6 +14,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
characterId: "\u72C2\u66B4\u72FC\u4EBA"
|
||||
characterName: "\u72C2\u66B4\u72FC\u4EBA"
|
||||
rarity: 2
|
||||
description:
|
||||
cardIcon: {fileID: 21300000, guid: 828dd51ecae0cc3418d2f1f675ffba3e, type: 3}
|
||||
unitPrefab: {fileID: 6708744566382593167, guid: f3b0d9efccd74475dbbbcdc1ddcdf129,
|
||||
|
||||
@@ -14,6 +14,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
characterId: shield_guard
|
||||
characterName: "\u76FE\u536B"
|
||||
rarity: 2
|
||||
description: "\u91CD\u88C5\u9632\u5FA1\u5355\u4F4D\uFF0C\u8840\u91CF\u6781\u9AD8\uFF0C\u79FB\u52A8\u7F13\u6162"
|
||||
cardIcon: {fileID: 21300000, guid: edea9239670494fc69b62e2fdc8525f5, type: 3}
|
||||
unitPrefab: {fileID: 1242979668690031507, guid: 5a43e36885a204515891085639dd22c4,
|
||||
|
||||
@@ -14,6 +14,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
characterId: "\u77F3\u5DE8\u4EBA"
|
||||
characterName: "\u77F3\u5DE8\u4EBA"
|
||||
rarity: 2
|
||||
description:
|
||||
cardIcon: {fileID: 21300000, guid: 7a686535436b593458a50fecbe0315ce, type: 3}
|
||||
unitPrefab: {fileID: 4471054466352856454, guid: 52e49b3af34914387b829cef0563b36e,
|
||||
|
||||
@@ -14,6 +14,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
characterId: elite_soldier
|
||||
characterName: "\u7CBE\u9510\u58EB\u5175"
|
||||
rarity: 2
|
||||
description: "\u9AD8\u7EA7\u8FD1\u6218\u5355\u4F4D\uFF0C\u653B\u9632\u517C\u5907\uFF0C\u6D88\u8017\u8F83\u9AD8"
|
||||
cardIcon: {fileID: 21300000, guid: b86682305b7af4a5983b9f24110d7055, type: 3}
|
||||
unitPrefab: {fileID: 3933539425749946856, guid: 6be579752d2424feea054ce267928002,
|
||||
|
||||
@@ -14,6 +14,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
characterId: "\u8352\u91CE\u4E4B\u738B"
|
||||
characterName: "\u8352\u91CE\u4E4B\u738B"
|
||||
rarity: 3
|
||||
description:
|
||||
cardIcon: {fileID: 0}
|
||||
unitPrefab: {fileID: 0}
|
||||
|
||||
@@ -14,6 +14,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
characterId: "\u8352\u91CE\u796D\u53F8"
|
||||
characterName: "\u8352\u91CE\u796D\u53F8"
|
||||
rarity: 2
|
||||
description:
|
||||
cardIcon: {fileID: 0}
|
||||
unitPrefab: {fileID: 0}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 部署格位高亮:拖动卡牌时在目标格位显示一块发光地板。
|
||||
/// 绿色 = 可以放置;红色 = 该格已被占用 / 不可放置。
|
||||
/// 全场只需要一个,由 DefenseGameFlowController 在布阵阶段创建。
|
||||
/// </summary>
|
||||
public class DeployHighlight : MonoBehaviour
|
||||
{
|
||||
public static DeployHighlight Instance { get; private set; }
|
||||
|
||||
private static readonly Color FreeColor = new Color(0.25f, 1f, 0.45f, 0.55f);
|
||||
private static readonly Color BlockedColor = new Color(1f, 0.28f, 0.28f, 0.55f);
|
||||
|
||||
private GameObject plate;
|
||||
private Material plateMaterial;
|
||||
private int shownCell = -1;
|
||||
|
||||
/// <summary>高亮当前是否可见。</summary>
|
||||
public bool IsVisible => plate != null && plate.activeSelf;
|
||||
|
||||
/// <summary>当前显示的是否是"不可放置"(红色)。</summary>
|
||||
public bool IsBlocked { get; private set; }
|
||||
|
||||
/// <summary>当前高亮所在的格位,-1 表示没有。</summary>
|
||||
public int ShownCell => shownCell;
|
||||
|
||||
public static DeployHighlight Ensure()
|
||||
{
|
||||
if (Instance != null) return Instance;
|
||||
|
||||
var go = new GameObject("DeployHighlight");
|
||||
Instance = go.AddComponent<DeployHighlight>();
|
||||
Instance.Build();
|
||||
return Instance;
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance == null)
|
||||
{
|
||||
Instance = this;
|
||||
Build();
|
||||
}
|
||||
}
|
||||
|
||||
private void Build()
|
||||
{
|
||||
if (plate != null) return;
|
||||
|
||||
plate = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
plate.name = "CellPlate";
|
||||
plate.transform.SetParent(transform, false);
|
||||
plate.transform.localRotation = Quaternion.identity;
|
||||
plate.transform.localScale = new Vector3(DeployGrid.CellWidth * 0.96f, 0.02f, DeployGrid.CellDepth * 0.96f);
|
||||
|
||||
// 高亮只是视觉提示,不需要碰撞
|
||||
var collider = plate.GetComponent<Collider>();
|
||||
if (collider != null)
|
||||
{
|
||||
Destroy(collider);
|
||||
}
|
||||
|
||||
var shader = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color");
|
||||
plateMaterial = new Material(shader);
|
||||
plateMaterial.name = "DeployHighlightMat";
|
||||
plateMaterial.color = FreeColor;
|
||||
|
||||
var renderer = plate.GetComponent<Renderer>();
|
||||
renderer.sharedMaterial = plateMaterial;
|
||||
renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
|
||||
renderer.receiveShadows = false;
|
||||
|
||||
plate.SetActive(false);
|
||||
}
|
||||
|
||||
/// <summary>在指定格位显示高亮。blocked = true 显示红色。</summary>
|
||||
public void Show(int cellIndex, bool blocked)
|
||||
{
|
||||
if (plate == null) Build();
|
||||
if (!DeployGrid.IsValidIndex(cellIndex))
|
||||
{
|
||||
Hide();
|
||||
return;
|
||||
}
|
||||
|
||||
var pos = DeployGrid.CellPosition(cellIndex);
|
||||
plate.transform.position = new Vector3(pos.x, DeployGrid.GridY + 0.05f, pos.z);
|
||||
plateMaterial.color = blocked ? BlockedColor : FreeColor;
|
||||
IsBlocked = blocked;
|
||||
|
||||
if (shownCell != cellIndex || !plate.activeSelf)
|
||||
{
|
||||
plate.SetActive(true);
|
||||
shownCell = cellIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public void Hide()
|
||||
{
|
||||
if (plate != null && plate.activeSelf)
|
||||
{
|
||||
plate.SetActive(false);
|
||||
}
|
||||
shownCell = -1;
|
||||
IsBlocked = false;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (Instance == this) Instance = null;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: W3JKtSP/Ai5L068yM/KfmfMqMzxNuuwNH7682DCQ2pexDdqL0sqt1zY=
|
||||
guid: XHkY4HmuWipU3pQUHG3woFO67ulNfp7xd8NigFzHi9m1Ba1ZVxVUNLM=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,291 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
/// <summary>
|
||||
/// 英雄卡片拖动组件(布阵阶段使用)。
|
||||
/// 拖动时在场景里生成一个半透明的英雄"幽灵"跟随指针,并吸附到最近的部署格位;
|
||||
/// 松手后把该卡对应的英雄登记到格位上,卡片进入"已使用"状态。
|
||||
/// </summary>
|
||||
public class HeroCardDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
|
||||
{
|
||||
[Header("配置(由 DefenseGameFlowController 注入)")]
|
||||
public int cardIndex; // 卡片序号,0 起
|
||||
public GameObject heroPrefab; // 对应英雄 Prefab
|
||||
public CharacterData characterData; // 角色数据
|
||||
|
||||
[Header("幽灵外观")]
|
||||
[Range(0.1f, 1f)] public float ghostAlpha = 0.55f;
|
||||
|
||||
private Canvas canvas;
|
||||
private CanvasGroup canvasGroup;
|
||||
private GameObject ghost;
|
||||
private Material ghostHiddenMaterial;
|
||||
|
||||
private bool dragging;
|
||||
private int currentCell = -1;
|
||||
|
||||
private const float PlacedCardAlpha = 0.35f;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
canvas = GetComponentInParent<Canvas>();
|
||||
canvasGroup = GetComponent<CanvasGroup>();
|
||||
if (canvasGroup == null)
|
||||
{
|
||||
canvasGroup = gameObject.AddComponent<CanvasGroup>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>由流程控制器注入卡片配置。</summary>
|
||||
public void Setup(int index, GameObject prefab, CharacterData data)
|
||||
{
|
||||
cardIndex = index;
|
||||
heroPrefab = prefab;
|
||||
characterData = data;
|
||||
SetPlaced(false);
|
||||
}
|
||||
|
||||
/// <summary>标记该卡是否已经放下去了(已放置的卡片变暗且不能再拖)。</summary>
|
||||
public void SetPlaced(bool placed)
|
||||
{
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
canvasGroup.alpha = placed ? PlacedCardAlpha : 1f;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
var flow = DefenseGameFlowController.Instance;
|
||||
if (flow == null || !flow.IsDeployPhase) return;
|
||||
if (flow.IsCardPlaced(cardIndex)) return; // 已经放置过了
|
||||
if (heroPrefab == null) return;
|
||||
|
||||
dragging = true;
|
||||
currentCell = -1;
|
||||
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
canvasGroup.alpha = 0.5f;
|
||||
canvasGroup.blocksRaycasts = false;
|
||||
}
|
||||
|
||||
CreateGhost();
|
||||
FollowPointer(eventData.position);
|
||||
}
|
||||
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
if (!dragging) return;
|
||||
FollowPointer(eventData.position);
|
||||
}
|
||||
|
||||
public void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
if (!dragging) return;
|
||||
dragging = false;
|
||||
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
canvasGroup.alpha = 1f;
|
||||
canvasGroup.blocksRaycasts = true;
|
||||
}
|
||||
|
||||
if (DeployHighlight.Instance != null) DeployHighlight.Instance.Hide();
|
||||
|
||||
int cell = currentCell;
|
||||
currentCell = -1;
|
||||
|
||||
DestroyGhost();
|
||||
|
||||
if (cell >= 0)
|
||||
{
|
||||
var flow = DefenseGameFlowController.Instance;
|
||||
if (flow != null && flow.PlaceHeroFromCard(cardIndex, cell))
|
||||
{
|
||||
SetPlaced(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── 幽灵 ────────────────────────────────────────────────
|
||||
|
||||
private void CreateGhost()
|
||||
{
|
||||
ghost = Instantiate(heroPrefab);
|
||||
ghost.name = "Ghost_" + heroPrefab.name;
|
||||
|
||||
// 只保留外观:关掉所有逻辑组件与碰撞体
|
||||
foreach (var behaviour in ghost.GetComponentsInChildren<Behaviour>(true))
|
||||
{
|
||||
if (behaviour is Animator) continue; // 保留 Animator 让它做待机动作
|
||||
behaviour.enabled = false;
|
||||
}
|
||||
foreach (var collider in ghost.GetComponentsInChildren<Collider>(true))
|
||||
{
|
||||
collider.enabled = false;
|
||||
}
|
||||
foreach (var rb in ghost.GetComponentsInChildren<Rigidbody>(true))
|
||||
{
|
||||
rb.isKinematic = true;
|
||||
rb.detectCollisions = false;
|
||||
}
|
||||
|
||||
// Animator 不能带动根位移,否则幽灵会自己漂走
|
||||
foreach (var animator in ghost.GetComponentsInChildren<Animator>(true))
|
||||
{
|
||||
animator.applyRootMotion = false;
|
||||
}
|
||||
|
||||
// 血条 UI 是 WorldHealthBar.Awake 生成的,幽灵不需要
|
||||
var healthBar = ghost.transform.Find("WorldHealthBar");
|
||||
if (healthBar != null)
|
||||
{
|
||||
Destroy(healthBar.gameObject);
|
||||
}
|
||||
|
||||
BuildGhostMaterials();
|
||||
}
|
||||
|
||||
private void BuildGhostMaterials()
|
||||
{
|
||||
if (ghostHiddenMaterial == null)
|
||||
{
|
||||
var hiddenShader = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color");
|
||||
ghostHiddenMaterial = new Material(hiddenShader);
|
||||
ghostHiddenMaterial.name = "GhostHidden";
|
||||
ghostHiddenMaterial.color = new Color(1f, 1f, 1f, 0f);
|
||||
}
|
||||
|
||||
var bodyShader = Shader.Find("Standard");
|
||||
|
||||
foreach (var renderer in ghost.GetComponentsInChildren<Renderer>(true))
|
||||
{
|
||||
var source = renderer.sharedMaterials;
|
||||
var result = new Material[source.Length];
|
||||
|
||||
for (int i = 0; i < source.Length; i++)
|
||||
{
|
||||
// 第 0 个材质是本体,做成半透明;其余(描边等附加材质)隐藏掉
|
||||
if (i == 0 && source[i] != null && bodyShader != null)
|
||||
{
|
||||
result[i] = MakeTransparent(source[i], ghostAlpha, bodyShader);
|
||||
}
|
||||
else
|
||||
{
|
||||
result[i] = ghostHiddenMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
renderer.sharedMaterials = result;
|
||||
renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
|
||||
}
|
||||
}
|
||||
|
||||
private static Material MakeTransparent(Material source, float alpha, Shader standard)
|
||||
{
|
||||
var mat = new Material(source);
|
||||
mat.name = source.name + "_Ghost";
|
||||
|
||||
// 统一用 Standard 的透明混合模式,保证任何贴图都能变成半透明
|
||||
if (mat.shader != standard)
|
||||
{
|
||||
var mainTex = mat.HasProperty("_MainTex") ? mat.GetTexture("_MainTex") : null;
|
||||
var color = mat.HasProperty("_Color") ? mat.GetColor("_Color") : Color.white;
|
||||
mat.shader = standard;
|
||||
if (mainTex != null) mat.SetTexture("_MainTex", mainTex);
|
||||
mat.SetColor("_Color", color);
|
||||
}
|
||||
|
||||
if (mat.HasProperty("_Mode"))
|
||||
{
|
||||
mat.SetFloat("_Mode", 3f); // Transparent
|
||||
mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
|
||||
mat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
||||
mat.SetInt("_ZWrite", 0);
|
||||
mat.DisableKeyword("_ALPHATEST_ON");
|
||||
mat.EnableKeyword("_ALPHABLEND_ON");
|
||||
mat.DisableKeyword("_ALPHAPREMULTIPLY_ON");
|
||||
mat.renderQueue = 3000;
|
||||
}
|
||||
|
||||
if (mat.HasProperty("_Color"))
|
||||
{
|
||||
var c = mat.GetColor("_Color");
|
||||
c.a = alpha;
|
||||
mat.SetColor("_Color", c);
|
||||
}
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
private void FollowPointer(Vector2 screenPosition)
|
||||
{
|
||||
if (ghost == null) return;
|
||||
|
||||
var cam = Camera.main;
|
||||
if (cam == null) return;
|
||||
|
||||
var ray = cam.ScreenPointToRay(screenPosition);
|
||||
var ground = new Plane(Vector3.up, new Vector3(0f, DeployGrid.UnitY, 0f));
|
||||
|
||||
if (!ground.Raycast(ray, out float distance))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 world = ray.GetPoint(distance);
|
||||
int cell = DeployGrid.SnapToCellClamped(world);
|
||||
|
||||
if (cell == currentCell) return;
|
||||
currentCell = cell;
|
||||
|
||||
var flow = DefenseGameFlowController.Instance;
|
||||
bool blocked = cell < 0 || (flow != null && flow.IsCellOccupied(cell));
|
||||
|
||||
if (cell >= 0)
|
||||
{
|
||||
ghost.transform.position = DeployGrid.CellPosition(cell);
|
||||
if (DeployHighlight.Instance != null) DeployHighlight.Instance.Show(cell, blocked);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 没吸附到格位:幽灵跟着指针但压暗提示不可放置
|
||||
ghost.transform.position = new Vector3(world.x, DeployGrid.UnitY, world.z);
|
||||
if (DeployHighlight.Instance != null) DeployHighlight.Instance.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
private void DestroyGhost()
|
||||
{
|
||||
if (ghost == null) return;
|
||||
|
||||
foreach (var renderer in ghost.GetComponentsInChildren<Renderer>(true))
|
||||
{
|
||||
if (renderer.sharedMaterials == null) continue;
|
||||
foreach (var mat in renderer.sharedMaterials)
|
||||
{
|
||||
if (mat != null && mat != ghostHiddenMaterial) Destroy(mat);
|
||||
}
|
||||
}
|
||||
|
||||
Destroy(ghost);
|
||||
ghost = null;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (dragging)
|
||||
{
|
||||
dragging = false;
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
canvasGroup.alpha = 1f;
|
||||
canvasGroup.blocksRaycasts = true;
|
||||
}
|
||||
if (DeployHighlight.Instance != null) DeployHighlight.Instance.Hide();
|
||||
}
|
||||
DestroyGhost();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: BihN5y6lVy1x4afDhOwE5/fM5e8mWQXxroZfuMUij3yrzemt9JIHQDA=
|
||||
guid: BnlMty2vUiow3BhqaXGezjZxgLO0vMhqB1RBSlrYGt9jhcgal1OINJI=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -9,6 +9,11 @@ public class HeroCardUI : MonoBehaviour
|
||||
{
|
||||
[Header("引用")]
|
||||
public Image iconImage; // 英雄头像
|
||||
public Image rarityFrameImage; // 稀有度边框
|
||||
public Sprite blueRarityFrame;
|
||||
public Sprite orangeRarityFrame;
|
||||
public Sprite purpleRarityFrame;
|
||||
public Sprite redRarityFrame;
|
||||
public Image hpFillImage; // 血条填充
|
||||
public GameObject deathPanel; // 死亡遮罩
|
||||
public Text reviveTimerText; // 复活倒计时文本
|
||||
@@ -86,21 +91,28 @@ public class HeroCardUI : MonoBehaviour
|
||||
/// 设置英雄单位
|
||||
/// </summary>
|
||||
public void SetHero(UnitBase unit, Sprite icon, Vector3 spawnPos)
|
||||
{
|
||||
SetHero(unit, icon, spawnPos, null);
|
||||
}
|
||||
|
||||
public void SetHero(UnitBase unit, Sprite icon, Vector3 spawnPos, CharacterData characterData)
|
||||
{
|
||||
heroUnit = unit;
|
||||
heroSpawnPosition = spawnPos;
|
||||
|
||||
|
||||
if (unit != null)
|
||||
{
|
||||
heroHealthBar = unit.GetComponent<WorldHealthBar>();
|
||||
}
|
||||
|
||||
// 设置头像
|
||||
if (iconImage != null && icon != null)
|
||||
{
|
||||
iconImage.sprite = icon;
|
||||
}
|
||||
|
||||
UpdateRarityFrame(characterData);
|
||||
UpdateCharacterName(characterData);
|
||||
|
||||
isDead = false;
|
||||
if (deathPanel != null)
|
||||
{
|
||||
@@ -108,6 +120,77 @@ public class HeroCardUI : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 只刷新卡面(头像 / 名字 / 稀有度边框),不绑定单位。
|
||||
/// 布阵阶段按玩家出战阵容初始化卡片时用,避免"卡片显示 A、拖出来却是 B"。
|
||||
/// </summary>
|
||||
public void SetCharacterInfo(CharacterData characterData)
|
||||
{
|
||||
if (characterData == null) return;
|
||||
|
||||
if (iconImage != null && characterData.cardIcon != null)
|
||||
{
|
||||
iconImage.sprite = characterData.cardIcon;
|
||||
}
|
||||
|
||||
UpdateRarityFrame(characterData);
|
||||
UpdateCharacterName(characterData);
|
||||
}
|
||||
|
||||
private void UpdateRarityFrame(CharacterData characterData)
|
||||
{
|
||||
if (rarityFrameImage == null)
|
||||
{
|
||||
Transform frame = transform.Find("RarityFrame") ?? transform.Find("稀有度边框");
|
||||
if (frame != null)
|
||||
{
|
||||
rarityFrameImage = frame.GetComponent<Image>();
|
||||
}
|
||||
}
|
||||
|
||||
if (rarityFrameImage == null || characterData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Sprite frameSprite = characterData.rarity switch
|
||||
{
|
||||
CharacterRarity.Blue => blueRarityFrame,
|
||||
CharacterRarity.Orange => orangeRarityFrame,
|
||||
CharacterRarity.Purple => purpleRarityFrame,
|
||||
CharacterRarity.Red => redRarityFrame,
|
||||
_ => blueRarityFrame
|
||||
};
|
||||
|
||||
if (frameSprite != null)
|
||||
{
|
||||
rarityFrameImage.sprite = frameSprite;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateCharacterName(CharacterData characterData)
|
||||
{
|
||||
if (characterData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 查找 NameLabel/Text
|
||||
Transform nameLabel = transform.Find("NameLabel");
|
||||
if (nameLabel != null)
|
||||
{
|
||||
Transform textTransform = nameLabel.Find("Text");
|
||||
if (textTransform != null)
|
||||
{
|
||||
Text nameText = textTransform.GetComponent<Text>();
|
||||
if (nameText != null)
|
||||
{
|
||||
nameText.text = characterData.characterName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新血条显示
|
||||
/// </summary>
|
||||
|
||||
@@ -245,7 +245,7 @@ public class BattleFormationSpawner : MonoBehaviour
|
||||
UnityEngine.Sprite icon = characterData != null ? characterData.cardIcon : null;
|
||||
|
||||
// 绑定英雄到卡片
|
||||
heroCardUI.SetHero(unitBase, icon, spawnPos);
|
||||
heroCardUI.SetHero(unitBase, icon, spawnPos, characterData);
|
||||
|
||||
spawnedHeroCount++;
|
||||
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 混沌之门:被占领后按固定间隔从所属阵营卡组随机出兵。
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(CrystalMineCapture))]
|
||||
public class ChaosGateSpawner : MonoBehaviour
|
||||
{
|
||||
[Header("出兵配置")]
|
||||
[Min(1f)] public float spawnInterval = 12f;
|
||||
[Min(0f)] public float spawnRadius = 1.5f;
|
||||
public bool spawnImmediatelyOnCapture = false;
|
||||
|
||||
[Header("蓝方卡组")]
|
||||
[SerializeField] private string[] blueDeckDataNames =
|
||||
{
|
||||
"人类士兵Data", "弓箭手Data", "盾卫Data", "精锐士兵Data",
|
||||
"法师Data", "狂暴狼人Data", "石巨人Data", "弓箭猎人Data"
|
||||
};
|
||||
|
||||
private CrystalMineCapture capture;
|
||||
private UnitTeam unitTeam;
|
||||
private float spawnTimer;
|
||||
private int previousTeamId = 2;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
capture = GetComponent<CrystalMineCapture>();
|
||||
unitTeam = GetComponent<UnitTeam>();
|
||||
spawnTimer = spawnInterval;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (unitTeam == null)
|
||||
{
|
||||
unitTeam = GetComponent<UnitTeam>();
|
||||
if (unitTeam == null) return;
|
||||
}
|
||||
|
||||
int currentTeamId = unitTeam.teamId;
|
||||
if (currentTeamId != previousTeamId)
|
||||
{
|
||||
previousTeamId = currentTeamId;
|
||||
spawnTimer = spawnImmediatelyOnCapture ? 0f : spawnInterval;
|
||||
}
|
||||
|
||||
if (currentTeamId != 0 && currentTeamId != 1)
|
||||
{
|
||||
spawnTimer = spawnInterval;
|
||||
return;
|
||||
}
|
||||
|
||||
spawnTimer -= Time.deltaTime;
|
||||
if (spawnTimer > 0f) return;
|
||||
|
||||
if (TrySpawn(currentTeamId))
|
||||
spawnTimer = spawnInterval;
|
||||
else
|
||||
spawnTimer = 1f;
|
||||
}
|
||||
|
||||
private bool TrySpawn(int teamId)
|
||||
{
|
||||
Vector3 position = transform.position;
|
||||
position.x += Random.Range(-spawnRadius, spawnRadius);
|
||||
position.z += Random.Range(-spawnRadius, spawnRadius);
|
||||
|
||||
if (teamId == 1)
|
||||
{
|
||||
EnemyCastleAI enemyAI = FindObjectOfType<EnemyCastleAI>();
|
||||
return enemyAI != null && enemyAI.TrySpawnFromPortal(position, transform.rotation);
|
||||
}
|
||||
|
||||
CharacterData card = ChooseBlueCard();
|
||||
if (card == null || CastleSpawnManager.Instance == null)
|
||||
return false;
|
||||
|
||||
return SpawnBlueUnit(card, position, transform.rotation);
|
||||
}
|
||||
|
||||
private CharacterData ChooseBlueCard()
|
||||
{
|
||||
CharacterData[] cards = new CharacterData[blueDeckDataNames.Length];
|
||||
int validCount = 0;
|
||||
foreach (string dataName in blueDeckDataNames)
|
||||
{
|
||||
CharacterData data = Resources.Load<CharacterData>("Data/" + dataName);
|
||||
if (data != null && data.unitPrefab != null)
|
||||
cards[validCount++] = data;
|
||||
}
|
||||
|
||||
if (validCount == 0) return null;
|
||||
|
||||
return cards[Random.Range(0, validCount)];
|
||||
}
|
||||
|
||||
private bool SpawnBlueUnit(CharacterData data, Vector3 position, Quaternion rotation)
|
||||
{
|
||||
GameObject unit = Instantiate(data.unitPrefab, position, rotation);
|
||||
UnitTeam team = unit.GetComponent<UnitTeam>();
|
||||
if (team != null)
|
||||
{
|
||||
team.teamId = 0;
|
||||
unit.tag = "Friend";
|
||||
}
|
||||
|
||||
UnitBase unitBase = unit.GetComponent<UnitBase>();
|
||||
if (unitBase != null)
|
||||
{
|
||||
unitBase.InitializeFromPlayerData(data.GetMaxHealth(1), data.GetAttackPower(1), data.GetMoveSpeed(1));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,599 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// 塔防模式游戏流程控制器
|
||||
/// 1. 开局进入布阵阶段:显示部署网格,玩家把底部英雄卡拖到格位上
|
||||
/// 2. 点击"开始游戏"后收起布阵 UI、显示血条并按波次出兵
|
||||
/// 3. 每波结束后英雄回到自己的格位(锚点)
|
||||
/// </summary>
|
||||
public class DefenseGameFlowController : MonoBehaviour
|
||||
{
|
||||
public static DefenseGameFlowController Instance { get; private set; }
|
||||
|
||||
[Header("引用")]
|
||||
public DefenseWaveLevelController waveLevelController;
|
||||
public Button startBattleButton;
|
||||
public GameObject deploymentUI; // 布阵 UI(英雄卡片面板)
|
||||
|
||||
[Header("英雄配置")]
|
||||
public HeroRoster roster;
|
||||
public Transform heroParent; // 生成英雄的父节点(战场/英雄)
|
||||
public int playerTeamId = 0;
|
||||
|
||||
[Header("布阵配置")]
|
||||
public int maxHeroCount = 5;
|
||||
public string deployGridObjectName = "部署网格"; // 战场 下的可见网格对象名
|
||||
|
||||
[Header("阵位守护")]
|
||||
[Tooltip("英雄只在「离自己格位不超过寻敌视野 detectionRange」的范围内接敌,避免一路推出去。")]
|
||||
public bool heroGuardPost = true;
|
||||
|
||||
// 布阵登记
|
||||
private readonly Dictionary<int, int> cardToCell = new Dictionary<int, int>(); // 卡片序号 -> 格位
|
||||
private readonly Dictionary<int, GameObject> cellToHero = new Dictionary<int, GameObject>(); // 格位 -> 英雄
|
||||
private readonly Dictionary<int, HeroCardDrag> cardDrags = new Dictionary<int, HeroCardDrag>();
|
||||
|
||||
// 已生成英雄
|
||||
private readonly List<GameObject> spawnedHeroes = new List<GameObject>();
|
||||
private readonly Dictionary<GameObject, Vector3> heroInitialPositions = new Dictionary<GameObject, Vector3>();
|
||||
private readonly List<GameObject> hiddenHeroBars = new List<GameObject>(); // 布阵阶段藏起来的血条
|
||||
|
||||
private GameObject deployGridRoot;
|
||||
private bool battleStarted;
|
||||
|
||||
/// <summary>true = 还在布阵阶段(可以拖动卡牌)。</summary>
|
||||
public bool IsDeployPhase => !battleStarted;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Instance = this;
|
||||
|
||||
// 场上不应该有预先摆好的英雄
|
||||
HideExistingHeroes();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (waveLevelController != null)
|
||||
{
|
||||
waveLevelController.autoStart = false;
|
||||
}
|
||||
|
||||
if (startBattleButton != null)
|
||||
{
|
||||
startBattleButton.onClick.AddListener(OnStartBattleClicked);
|
||||
startBattleButton.interactable = true;
|
||||
}
|
||||
|
||||
if (deploymentUI != null)
|
||||
{
|
||||
deploymentUI.SetActive(true);
|
||||
}
|
||||
|
||||
SetupDeployGrid();
|
||||
DeployHighlight.Ensure();
|
||||
InitializeCardDrag();
|
||||
|
||||
Debug.Log("DefenseGameFlowController: 布阵阶段,把英雄卡拖到网格上。");
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (battleStarted) return;
|
||||
|
||||
// 布阵阶段:点击已经放好的英雄可以把他撤下来
|
||||
if (!TryGetTap(out Vector2 screenPosition)) return;
|
||||
if (IsPointerOverUI()) return;
|
||||
|
||||
var camera = Camera.main;
|
||||
if (camera == null) return;
|
||||
|
||||
var ray = camera.ScreenPointToRay(screenPosition);
|
||||
if (!Physics.Raycast(ray, out RaycastHit hit, 300f, ~0, QueryTriggerInteraction.Collide)) return;
|
||||
|
||||
var unit = hit.collider.GetComponentInParent<UnitBase>();
|
||||
if (unit != null && spawnedHeroes.Contains(unit.gameObject))
|
||||
{
|
||||
RemoveHero(unit.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (Instance == this) Instance = null;
|
||||
}
|
||||
|
||||
// ── 布阵阶段 ────────────────────────────────────────────
|
||||
|
||||
/// <summary>隐藏场景里预先摆好的英雄。</summary>
|
||||
private void HideExistingHeroes()
|
||||
{
|
||||
foreach (var unit in FindObjectsOfType<UnitBase>(true))
|
||||
{
|
||||
unit.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>找到可见的部署网格,摆正到 DeployGrid 定义的位置并显示。</summary>
|
||||
private void SetupDeployGrid()
|
||||
{
|
||||
var battlefield = GameObject.Find("战场");
|
||||
if (battlefield != null)
|
||||
{
|
||||
var child = battlefield.transform.Find(deployGridObjectName);
|
||||
if (child != null) deployGridRoot = child.gameObject;
|
||||
}
|
||||
if (deployGridRoot == null)
|
||||
{
|
||||
deployGridRoot = GameObject.Find(deployGridObjectName);
|
||||
}
|
||||
if (deployGridRoot == null)
|
||||
{
|
||||
Debug.LogWarning($"DefenseGameFlowController: 没找到部署网格对象「{deployGridObjectName}」。");
|
||||
return;
|
||||
}
|
||||
|
||||
AlignGridCells(deployGridRoot.transform);
|
||||
deployGridRoot.SetActive(true);
|
||||
}
|
||||
|
||||
/// <summary>把网格下的格位按 DeployGrid 的坐标摆好,保证视觉与吸附完全一致。</summary>
|
||||
private static void AlignGridCells(Transform gridRoot)
|
||||
{
|
||||
gridRoot.localPosition = new Vector3(0f, DeployGrid.GridY, 0f);
|
||||
gridRoot.localRotation = Quaternion.identity;
|
||||
|
||||
int count = gridRoot.childCount;
|
||||
if (count == 0) return;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var cell = gridRoot.GetChild(i);
|
||||
int index = ParseCellIndex(cell.name, i);
|
||||
if (!DeployGrid.IsValidIndex(index)) continue;
|
||||
|
||||
var pos = DeployGrid.CellPosition(index);
|
||||
cell.localPosition = new Vector3(pos.x, 0f, pos.z);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>格位命名形如「格位_3_4」(行_列,从 1 开始);解析失败时退回顺序索引。</summary>
|
||||
private static int ParseCellIndex(string name, int fallback)
|
||||
{
|
||||
var parts = name.Split('_');
|
||||
if (parts.Length >= 3
|
||||
&& int.TryParse(parts[parts.Length - 2], out int row)
|
||||
&& int.TryParse(parts[parts.Length - 1], out int col))
|
||||
{
|
||||
int r = row - 1;
|
||||
int c = col - 1;
|
||||
if (r >= 0 && r < DeployGrid.Rows && c >= 0 && c < DeployGrid.Cols)
|
||||
{
|
||||
return DeployGrid.ToIndex(r, c);
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按玩家出战阵容(PlayerData)给底部每张英雄卡挂上拖动组件,并刷新卡面。
|
||||
/// 站位不再从 PlayerData 读取(改成开局手动布阵),但「用哪几个角色」仍然读 PlayerData。
|
||||
/// </summary>
|
||||
private void InitializeCardDrag()
|
||||
{
|
||||
var canvasObj = GameObject.Find("TowerDefenseCanvas");
|
||||
if (canvasObj == null)
|
||||
{
|
||||
Debug.LogWarning("DefenseGameFlowController: 没找到 TowerDefenseCanvas。");
|
||||
return;
|
||||
}
|
||||
|
||||
var heroPanel = canvasObj.transform.Find("BottomUI/HeroCardsPanel");
|
||||
if (heroPanel == null)
|
||||
{
|
||||
Debug.LogWarning("DefenseGameFlowController: 没找到 BottomUI/HeroCardsPanel。");
|
||||
return;
|
||||
}
|
||||
|
||||
var deck = GetDeckCharacters();
|
||||
|
||||
for (int i = 0; i < maxHeroCount; i++)
|
||||
{
|
||||
var cardObj = heroPanel.Find($"HeroCard{i + 1}");
|
||||
if (cardObj == null) continue;
|
||||
|
||||
var drag = cardObj.GetComponent<HeroCardDrag>();
|
||||
if (drag == null)
|
||||
{
|
||||
drag = cardObj.gameObject.AddComponent<HeroCardDrag>();
|
||||
}
|
||||
|
||||
var data = i < deck.Length ? deck[i] : null;
|
||||
drag.Setup(i, data != null ? data.unitPrefab : null, data);
|
||||
cardDrags[i] = drag;
|
||||
|
||||
// 卡面(头像 / 名字 / 稀有度)也和出战阵容保持一致
|
||||
var cardUI = cardObj.GetComponent<HeroCardUI>();
|
||||
if (cardUI != null && data != null)
|
||||
{
|
||||
cardUI.SetCharacterInfo(data);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"DefenseGameFlowController: 已按出战阵容开启 {cardDrags.Count} 张卡片的拖动。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取玩家出战阵容(PlayerData.json 的 currentDeck),按槽位返回角色数据。
|
||||
/// PlayerData 不可用时回退到场景里配置的 HeroRoster。
|
||||
/// </summary>
|
||||
private CharacterData[] GetDeckCharacters()
|
||||
{
|
||||
var deck = new CharacterData[maxHeroCount];
|
||||
var allData = Resources.LoadAll<CharacterData>("Data");
|
||||
|
||||
if (PlayerDataManager.Instance != null)
|
||||
{
|
||||
for (int i = 0; i < maxHeroCount; i++)
|
||||
{
|
||||
var owned = PlayerDataManager.Instance.GetDeckCharacter(i);
|
||||
if (owned == null || string.IsNullOrEmpty(owned.characterId)) continue;
|
||||
|
||||
foreach (var data in allData)
|
||||
{
|
||||
if (data == null || data.characterId != owned.characterId) continue;
|
||||
if (data.unitPrefab == null) break; // 只有数据的角色(如荒野之王)不能出战
|
||||
deck[i] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 兜底:PlayerData 没给出阵容时用 HeroRoster
|
||||
bool anyDeck = false;
|
||||
foreach (var d in deck) if (d != null) { anyDeck = true; break; }
|
||||
|
||||
if (!anyDeck && roster != null && roster.heroes != null)
|
||||
{
|
||||
for (int i = 0; i < roster.heroes.Length && i < maxHeroCount; i++)
|
||||
{
|
||||
var entry = roster.heroes[i];
|
||||
if (entry == null || entry.prefab == null) continue;
|
||||
deck[i] = FindCharacterDataForPrefab(entry.prefab);
|
||||
}
|
||||
}
|
||||
|
||||
return deck;
|
||||
}
|
||||
|
||||
/// <summary>把某张卡的英雄放到格位上。成功返回 true。</summary>
|
||||
public bool PlaceHeroFromCard(int cardIndex, int cellIndex)
|
||||
{
|
||||
if (battleStarted) return false;
|
||||
if (cardIndex < 0 || cardIndex >= maxHeroCount) return false;
|
||||
if (!DeployGrid.IsValidIndex(cellIndex)) return false;
|
||||
if (IsCardPlaced(cardIndex)) return false;
|
||||
if (IsCellOccupied(cellIndex)) return false;
|
||||
|
||||
if (!cardDrags.TryGetValue(cardIndex, out var drag) || drag == null || drag.heroPrefab == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var hero = SpawnHero(drag.heroPrefab, cellIndex, cardIndex);
|
||||
if (hero == null) return false;
|
||||
|
||||
cardToCell[cardIndex] = cellIndex;
|
||||
cellToHero[cellIndex] = hero;
|
||||
|
||||
Debug.Log($"布阵: 第 {cardIndex + 1} 张卡 → 格位 {cellIndex} ({hero.name})");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>撤销某个格位上的英雄,并让对应卡片恢复可用。</summary>
|
||||
public void RemoveHeroAt(int cellIndex)
|
||||
{
|
||||
if (cellToHero.TryGetValue(cellIndex, out var hero) && hero != null)
|
||||
{
|
||||
RemoveHero(hero);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveHero(GameObject hero)
|
||||
{
|
||||
int cardIndex = -1;
|
||||
foreach (var kv in cardToCell)
|
||||
{
|
||||
if (cellToHero.TryGetValue(kv.Value, out var h) && h == hero)
|
||||
{
|
||||
cardIndex = kv.Key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cardIndex >= 0)
|
||||
{
|
||||
cardToCell.Remove(cardIndex);
|
||||
if (cardDrags.TryGetValue(cardIndex, out var drag) && drag != null)
|
||||
{
|
||||
drag.SetPlaced(false);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var kv in new List<KeyValuePair<int, GameObject>>(cellToHero))
|
||||
{
|
||||
if (kv.Value == hero) cellToHero.Remove(kv.Key);
|
||||
}
|
||||
|
||||
spawnedHeroes.Remove(hero);
|
||||
heroInitialPositions.Remove(hero);
|
||||
|
||||
Debug.Log($"撤回英雄: {hero.name}");
|
||||
Destroy(hero);
|
||||
}
|
||||
|
||||
public bool IsCellOccupied(int cellIndex)
|
||||
{
|
||||
return cellToHero.TryGetValue(cellIndex, out var hero) && hero != null;
|
||||
}
|
||||
|
||||
public bool IsCardPlaced(int cardIndex)
|
||||
{
|
||||
return cardToCell.ContainsKey(cardIndex);
|
||||
}
|
||||
|
||||
public int GetCellOfCard(int cardIndex)
|
||||
{
|
||||
return cardToCell.TryGetValue(cardIndex, out int cell) ? cell : -1;
|
||||
}
|
||||
|
||||
// ── 开战 ────────────────────────────────────────────────
|
||||
|
||||
private void OnStartBattleClicked()
|
||||
{
|
||||
if (battleStarted) return;
|
||||
battleStarted = true;
|
||||
|
||||
if (deploymentUI != null) deploymentUI.SetActive(false);
|
||||
if (startBattleButton != null) startBattleButton.gameObject.SetActive(false);
|
||||
if (deployGridRoot != null) deployGridRoot.SetActive(false);
|
||||
if (DeployHighlight.Instance != null) DeployHighlight.Instance.Hide();
|
||||
|
||||
// 卡片从"待放置"切换成"英雄状态显示":恢复满不透明度
|
||||
foreach (var drag in cardDrags.Values)
|
||||
{
|
||||
if (drag != null) drag.SetPlaced(false);
|
||||
}
|
||||
|
||||
// 一个都没布置时用默认阵型兜底
|
||||
if (cellToHero.Count == 0)
|
||||
{
|
||||
SpawnDefaultFormation();
|
||||
}
|
||||
|
||||
// 布阵阶段藏起来的血条,开战后显示
|
||||
foreach (var barObject in hiddenHeroBars)
|
||||
{
|
||||
if (barObject != null) barObject.SetActive(true);
|
||||
}
|
||||
|
||||
Debug.Log("DefenseGameFlowController: 开始游戏,出兵!");
|
||||
StartCoroutine(StartBattleSequence());
|
||||
}
|
||||
|
||||
private IEnumerator StartBattleSequence()
|
||||
{
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
if (waveLevelController != null)
|
||||
{
|
||||
StartCoroutine(waveLevelController.StartLevel());
|
||||
}
|
||||
}
|
||||
|
||||
// ── 生成英雄 ────────────────────────────────────────────
|
||||
|
||||
private GameObject SpawnHero(GameObject prefab, int cell, int cardIndex)
|
||||
{
|
||||
var characterData = FindCharacterDataForPrefab(prefab);
|
||||
var spawnPos = DeployGrid.CellPosition(cell);
|
||||
|
||||
var unit = Instantiate(prefab, spawnPos, Quaternion.identity);
|
||||
unit.name = "英雄_" + prefab.name;
|
||||
|
||||
if (heroParent != null)
|
||||
{
|
||||
unit.transform.SetParent(heroParent, true);
|
||||
}
|
||||
|
||||
var team = unit.GetComponent<UnitTeam>();
|
||||
if (team != null) team.teamId = playerTeamId;
|
||||
|
||||
var unitBase = unit.GetComponent<UnitBase>();
|
||||
if (unitBase != null)
|
||||
{
|
||||
unitBase.returnToAnchorWhenIdle = true;
|
||||
unitBase.anchorArrivalDistance = 0.35f;
|
||||
// 阵位守护:接敌范围直接用单位自己的寻敌视野 detectionRange
|
||||
unitBase.useAnchorLeash = heroGuardPost;
|
||||
unitBase.ResetAnchorPosition();
|
||||
}
|
||||
|
||||
if (characterData != null && unitBase != null)
|
||||
{
|
||||
var playerData = PlayerDataManager.Instance != null
|
||||
? PlayerDataManager.Instance.GetCharacterData(characterData.characterId)
|
||||
: null;
|
||||
int level = playerData != null ? playerData.level : 1;
|
||||
unitBase.InitializeFromPlayerData(
|
||||
characterData.GetMaxHealth(level),
|
||||
characterData.GetAttackPower(level),
|
||||
characterData.GetMoveSpeed(level));
|
||||
}
|
||||
|
||||
var healthBar = unit.GetComponent<WorldHealthBar>();
|
||||
if (healthBar != null)
|
||||
{
|
||||
if (playerTeamId == 0) healthBar.canRevive = true;
|
||||
|
||||
// 布阵阶段把血条收起来,开战时再显示(血条是 WorldHealthBar.Awake 生成的子物体)
|
||||
var barObject = unit.transform.Find("WorldHealthBar");
|
||||
if (barObject != null && !battleStarted)
|
||||
{
|
||||
barObject.gameObject.SetActive(false);
|
||||
hiddenHeroBars.Add(barObject.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
spawnedHeroes.Add(unit);
|
||||
heroInitialPositions[unit] = spawnPos;
|
||||
|
||||
BindHeroToCard(unit, characterData, spawnPos, cardIndex);
|
||||
|
||||
return unit;
|
||||
}
|
||||
|
||||
/// <summary>一张都没摆时用出战阵容按"近战前排 / 远程后排"兜底。</summary>
|
||||
private void SpawnDefaultFormation()
|
||||
{
|
||||
var deck = GetDeckCharacters();
|
||||
|
||||
int meleeTotal = 0, rangedTotal = 0;
|
||||
for (int i = 0; i < deck.Length; i++)
|
||||
{
|
||||
if (deck[i] == null) continue;
|
||||
if (IsMelee(deck[i])) meleeTotal++; else rangedTotal++;
|
||||
}
|
||||
|
||||
var used = new HashSet<int>();
|
||||
int meleeIndex = 0, rangedIndex = 0, spawned = 0;
|
||||
|
||||
for (int i = 0; i < deck.Length && spawned < maxHeroCount; i++)
|
||||
{
|
||||
var data = deck[i];
|
||||
if (data == null || data.unitPrefab == null) continue;
|
||||
|
||||
int cell = IsMelee(data)
|
||||
? DeployGrid.DefaultCell(true, meleeIndex++, meleeTotal)
|
||||
: DeployGrid.DefaultCell(false, rangedIndex++, rangedTotal);
|
||||
|
||||
if (used.Contains(cell)) cell = NextFreeCell(cell, used);
|
||||
if (cell < 0) continue;
|
||||
|
||||
used.Add(cell);
|
||||
if (SpawnHero(data.unitPrefab, cell, i) == null) continue;
|
||||
|
||||
cellToHero[cell] = spawnedHeroes[spawnedHeroes.Count - 1];
|
||||
spawned++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>判定角色是否近战(远程单位 attackType 为 RangedProjectile)。</summary>
|
||||
private static bool IsMelee(CharacterData data)
|
||||
{
|
||||
// 用"是否配置了投射物"来判定更可靠:RangedProjectile 一定有 projectilePrefab
|
||||
return data.unitPrefab == null || data.unitPrefab.GetComponent<UnitBase>()?.attackType != UnitBase.AttackType.RangedProjectile;
|
||||
}
|
||||
|
||||
private static int NextFreeCell(int from, HashSet<int> used)
|
||||
{
|
||||
for (int i = 0; i < DeployGrid.CellCount; i++)
|
||||
{
|
||||
int candidate = (from + i) % DeployGrid.CellCount;
|
||||
if (!used.Contains(candidate)) return candidate;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>把英雄绑到它来源的那张卡片上(显示名字 / 稀有度 / 血条)。</summary>
|
||||
private void BindHeroToCard(GameObject heroUnit, CharacterData characterData, Vector3 spawnPos, int cardIndex)
|
||||
{
|
||||
if (cardIndex < 0 || cardIndex >= maxHeroCount) return;
|
||||
if (!cardDrags.TryGetValue(cardIndex, out var drag) || drag == null) return;
|
||||
|
||||
var cardUI = drag.GetComponent<HeroCardUI>();
|
||||
var unitBase = heroUnit.GetComponent<UnitBase>();
|
||||
if (cardUI == null || unitBase == null) return;
|
||||
|
||||
var icon = characterData != null ? characterData.cardIcon : null;
|
||||
cardUI.SetHero(unitBase, icon, spawnPos, characterData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 一波清完后让英雄回格位。
|
||||
/// 正常情况放开目标,让 UnitBase 自己走回格位;只有寻路真的不可用(卡住)时才瞬移兜底。
|
||||
/// </summary>
|
||||
public void ResetHeroPositions()
|
||||
{
|
||||
foreach (var hero in spawnedHeroes)
|
||||
{
|
||||
if (hero == null || !hero.activeSelf) continue;
|
||||
|
||||
var unitBase = hero.GetComponent<UnitBase>();
|
||||
var navAgent = hero.GetComponent<UnityEngine.AI.NavMeshAgent>();
|
||||
|
||||
bool canWalk = UnityEngine.AI.NavMesh.SamplePosition(
|
||||
hero.transform.position, out _, 2f, UnityEngine.AI.NavMesh.AllAreas);
|
||||
|
||||
if (navAgent != null && navAgent.enabled && canWalk)
|
||||
{
|
||||
if (unitBase != null) unitBase.target = null; // 放开目标,进入回位
|
||||
navAgent.isStopped = false;
|
||||
navAgent.ResetPath();
|
||||
continue;
|
||||
}
|
||||
|
||||
// 卡住了(比如被挤出 NavMesh)才直接摆回格位
|
||||
if (heroInitialPositions.TryGetValue(hero, out var initialPos))
|
||||
{
|
||||
Debug.LogWarning($"DefenseGameFlowController: {hero.name} 寻路不可用,瞬移回格位");
|
||||
hero.transform.position = initialPos;
|
||||
if (navAgent != null) navAgent.nextPosition = initialPos;
|
||||
if (unitBase != null) unitBase.ResetAnchorPosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── 工具 ────────────────────────────────────────────────
|
||||
|
||||
private CharacterData FindCharacterDataForPrefab(GameObject prefab)
|
||||
{
|
||||
if (prefab == null) return null;
|
||||
foreach (var data in Resources.LoadAll<CharacterData>("Data"))
|
||||
{
|
||||
if (data != null && data.unitPrefab == prefab) return data;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool TryGetTap(out Vector2 screenPosition)
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
screenPosition = Input.mousePosition;
|
||||
return true;
|
||||
}
|
||||
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
|
||||
{
|
||||
screenPosition = Input.GetTouch(0).position;
|
||||
return true;
|
||||
}
|
||||
screenPosition = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsPointerOverUI()
|
||||
{
|
||||
if (EventSystem.current == null) return false;
|
||||
|
||||
if (Input.touchCount > 0)
|
||||
{
|
||||
return EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId);
|
||||
}
|
||||
return EventSystem.current.IsPointerOverGameObject();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: CXkWsyr5V3PqLCVXf9kh9UDgagA4PNu+m8m3e+26o8Vi3MvAgRRmtzA=
|
||||
guid: B38YtCOpVSouc7G4rbHoBIMoJtLgT79fWI15sJ401Ny0ANjUOgZHriM=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -59,6 +59,19 @@ public class DefenseWaveLevelController : MonoBehaviour
|
||||
if (autoStart) StartCoroutine(RunLevel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 外部调用:开始关卡(用于游戏流程控制)
|
||||
/// </summary>
|
||||
public IEnumerator StartLevel()
|
||||
{
|
||||
if (level == null || level.waves == null || level.waves.Length == 0)
|
||||
{
|
||||
Debug.LogError("DefenseWaveLevelController: 无法启动关卡,波次数据未加载");
|
||||
yield break;
|
||||
}
|
||||
yield return RunLevel();
|
||||
}
|
||||
|
||||
private bool LoadLevel()
|
||||
{
|
||||
if (levelJson == null)
|
||||
@@ -88,12 +101,29 @@ public class DefenseWaveLevelController : MonoBehaviour
|
||||
yield return new WaitForSeconds(Mathf.Max(0f, wave.restBeforeWave));
|
||||
yield return SpawnWave(wave);
|
||||
yield return WaitForWaveCleared();
|
||||
|
||||
// 每波结束后,让英雄回到初始位置
|
||||
ResetHeroPositionsAfterWave();
|
||||
|
||||
yield return new WaitForSeconds(Mathf.Max(0f, waveCompleteDelay));
|
||||
}
|
||||
|
||||
UpdateProgress(level.waves.Length, level.waves.Length, "通关");
|
||||
Debug.Log("DefenseWaveLevelController: 第一关波次全部完成。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 每波结束后让英雄回到初始位置
|
||||
/// </summary>
|
||||
private void ResetHeroPositionsAfterWave()
|
||||
{
|
||||
DefenseGameFlowController flowController = FindObjectOfType<DefenseGameFlowController>();
|
||||
if (flowController != null)
|
||||
{
|
||||
flowController.ResetHeroPositions();
|
||||
Debug.Log($"第 {currentWaveIndex + 1} 波结束,英雄回到初始位置");
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator SpawnWave(WaveEntry wave)
|
||||
{
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class Barracks : MonoBehaviour
|
||||
{
|
||||
[Header("角色数据")]
|
||||
public CharacterData characterData;
|
||||
|
||||
[Header("阵营")]
|
||||
public string unitTag = "Friend";
|
||||
|
||||
[Header("生产设置")]
|
||||
public Transform spawnPoint; // 单位生成位置
|
||||
|
||||
[Header("UI显示")]
|
||||
public Image progressBar; // 生产进度条
|
||||
public Image characterIcon; // 角色头像
|
||||
|
||||
private float spawnTimer = 0f;
|
||||
private float spawnInterval = 5f;
|
||||
private bool isProducing = true;
|
||||
private BuildingHealth buildingHealth;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
buildingHealth = GetComponent<BuildingHealth>();
|
||||
|
||||
if (characterData != null)
|
||||
{
|
||||
spawnInterval = 5f;
|
||||
|
||||
// 设置角色头像
|
||||
if (characterIcon != null && characterData.cardIcon != null)
|
||||
{
|
||||
characterIcon.sprite = characterData.cardIcon;
|
||||
}
|
||||
|
||||
Debug.Log($"兵营初始化:{characterData.characterName},生产间隔{spawnInterval}秒");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("兵营缺少角色数据!");
|
||||
}
|
||||
|
||||
// 如果没有spawnPoint,使用兵营自己的位置
|
||||
if (spawnPoint == null)
|
||||
{
|
||||
spawnPoint = transform;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!isProducing || characterData == null) return;
|
||||
|
||||
spawnTimer += Time.deltaTime;
|
||||
|
||||
// 更新进度条
|
||||
if (buildingHealth != null)
|
||||
{
|
||||
buildingHealth.SetProductionProgress(spawnTimer / spawnInterval);
|
||||
}
|
||||
else if (progressBar != null)
|
||||
{
|
||||
progressBar.fillAmount = spawnTimer / spawnInterval;
|
||||
}
|
||||
|
||||
// 时间到,生产单位
|
||||
if (spawnTimer >= spawnInterval)
|
||||
{
|
||||
SpawnUnit();
|
||||
spawnTimer = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
private void SpawnUnit()
|
||||
{
|
||||
if (characterData == null || characterData.unitPrefab == null)
|
||||
{
|
||||
Debug.LogError("无法生产单位:缺少unitPrefab");
|
||||
return;
|
||||
}
|
||||
|
||||
// 在spawnPoint位置生成单位
|
||||
Vector3 spawnPosition = spawnPoint.position;
|
||||
|
||||
GameObject unit = Instantiate(characterData.unitPrefab, spawnPosition, Quaternion.identity);
|
||||
unit.name = characterData.characterName;
|
||||
unit.tag = unitTag;
|
||||
|
||||
// 设置阵营 ID(根据建筑的阵营)
|
||||
var buildingTeam = GetComponent<UnitTeam>();
|
||||
var unitTeam = unit.GetComponent<UnitTeam>();
|
||||
if (buildingTeam != null && unitTeam != null)
|
||||
{
|
||||
unitTeam.teamId = buildingTeam.teamId;
|
||||
}
|
||||
else if (unitTeam != null)
|
||||
{
|
||||
// 兜底:根据 tag 判断阵营
|
||||
unitTeam.teamId = unitTag == "Friend" ? 0 : 1;
|
||||
}
|
||||
|
||||
// 如果单位有UnitBase组件,使用1级属性初始化
|
||||
var unitBase = unit.GetComponent<UnitBase>();
|
||||
if (unitBase != null)
|
||||
{
|
||||
float health = characterData.GetMaxHealth(1);
|
||||
float attack = characterData.GetAttackPower(1);
|
||||
float moveSpeed = characterData.GetMoveSpeed(1);
|
||||
|
||||
unitBase.InitializeFromPlayerData(health, attack, moveSpeed);
|
||||
}
|
||||
|
||||
Debug.Log($"兵营生产了单位:{characterData.characterName}");
|
||||
}
|
||||
|
||||
public void StopProduction()
|
||||
{
|
||||
isProducing = false;
|
||||
}
|
||||
|
||||
public void StartProduction()
|
||||
{
|
||||
isProducing = true;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(WorldHealthBar))]
|
||||
public class BuildingHealth : MonoBehaviour
|
||||
{
|
||||
[Header("建筑生命")]
|
||||
[Min(1f)] public float maxHealth = 500f;
|
||||
|
||||
private WorldHealthBar healthBar;
|
||||
|
||||
public float ProductionProgress => healthBar != null
|
||||
? Mathf.Clamp01(healthBar.currentEnergy / healthBar.maxEnergy)
|
||||
: 0f;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
healthBar = GetComponent<WorldHealthBar>();
|
||||
healthBar.maxHealth = maxHealth;
|
||||
healthBar.currentHealth = maxHealth;
|
||||
healthBar.maxEnergy = 1f;
|
||||
healthBar.currentEnergy = 0f;
|
||||
}
|
||||
|
||||
public void SetProductionProgress(float normalizedProgress)
|
||||
{
|
||||
if (healthBar != null)
|
||||
{
|
||||
healthBar.SetEnergy(Mathf.Clamp01(normalizedProgress) * healthBar.maxEnergy);
|
||||
}
|
||||
}
|
||||
|
||||
public bool ReceiveDamage(float damage, GameObject attacker = null)
|
||||
{
|
||||
if (damage <= 0f || healthBar == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
healthBar.TakeDamage(damage);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,242 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class BuildingPlacementManager : MonoBehaviour
|
||||
{
|
||||
public static BuildingPlacementManager Instance { get; private set; }
|
||||
|
||||
[Header("建筑预制体")]
|
||||
public GameObject barracksBasePrefab;
|
||||
public GameObject goldMinePrefab;
|
||||
|
||||
[Header("虚拟网格")]
|
||||
[Min(0.1f)] public float gridSize = 1f;
|
||||
[Min(0f)] public float placementHeight;
|
||||
public Vector2 xLimits = new Vector2(-7f, 7f);
|
||||
public Vector2 zLimits = new Vector2(-10f, 20f);
|
||||
|
||||
[Header("放置检测")]
|
||||
public LayerMask groundLayer;
|
||||
[Min(0.1f)] public float buildingRadius = 1.25f;
|
||||
public Material previewMaterialValid;
|
||||
public Material previewMaterialInvalid;
|
||||
|
||||
private readonly List<GameObject> placedBuildings = new List<GameObject>();
|
||||
private CharacterData currentCharacterData;
|
||||
private GameObject currentPrefab;
|
||||
private GameObject previewObject;
|
||||
private Camera mainCamera;
|
||||
private bool isPlacing;
|
||||
private bool previewPositionValid;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
mainCamera = Camera.main;
|
||||
RegisterExistingBuilding(GameObject.Find("主要基地"));
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!isPlacing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UpdatePreview();
|
||||
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
TryPlaceBuilding();
|
||||
}
|
||||
else if (Input.GetMouseButtonDown(1) || Input.GetKeyDown(KeyCode.Escape))
|
||||
{
|
||||
CancelPlacement();
|
||||
}
|
||||
}
|
||||
|
||||
public void StartPlacingBuilding(CharacterData data)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
StartPlacingBarracks(data);
|
||||
}
|
||||
|
||||
public void StartPlacingBarracks(CharacterData data)
|
||||
{
|
||||
if (data == null || barracksBasePrefab == null)
|
||||
{
|
||||
Debug.LogError("兵营预制体或角色数据为空");
|
||||
return;
|
||||
}
|
||||
|
||||
BeginPlacement(barracksBasePrefab, data);
|
||||
}
|
||||
|
||||
public void StartPlacingGoldMine()
|
||||
{
|
||||
if (goldMinePrefab == null)
|
||||
{
|
||||
Debug.LogError("金矿预制体为空");
|
||||
return;
|
||||
}
|
||||
|
||||
BeginPlacement(goldMinePrefab, null);
|
||||
}
|
||||
|
||||
private void BeginPlacement(GameObject prefab, CharacterData data)
|
||||
{
|
||||
CancelPlacement();
|
||||
currentPrefab = prefab;
|
||||
currentCharacterData = data;
|
||||
previewObject = Instantiate(prefab);
|
||||
previewObject.name = "建筑预览";
|
||||
SetCollidersEnabled(previewObject, false);
|
||||
isPlacing = true;
|
||||
mainCamera = Camera.main;
|
||||
}
|
||||
|
||||
private void UpdatePreview()
|
||||
{
|
||||
if (previewObject == null || mainCamera == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
|
||||
int mask = groundLayer.value == 0 ? Physics.DefaultRaycastLayers : groundLayer.value;
|
||||
if (!Physics.Raycast(ray, out RaycastHit hit, 1000f, mask))
|
||||
{
|
||||
previewPositionValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 position = hit.point;
|
||||
position.x = Mathf.Round(position.x / gridSize) * gridSize;
|
||||
position.y = placementHeight;
|
||||
position.z = Mathf.Round(position.z / gridSize) * gridSize;
|
||||
previewObject.transform.position = position;
|
||||
previewPositionValid = IsValidPosition(position);
|
||||
UpdatePreviewMaterial(previewPositionValid);
|
||||
}
|
||||
|
||||
private bool IsValidPosition(Vector3 position)
|
||||
{
|
||||
if (position.x < xLimits.x || position.x > xLimits.y ||
|
||||
position.z < zLimits.x || position.z > zLimits.y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (GameObject building in placedBuildings)
|
||||
{
|
||||
if (building != null && Vector3.Distance(position, building.transform.position) < buildingRadius * 2f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void TryPlaceBuilding()
|
||||
{
|
||||
if (!previewPositionValid || previewObject == null || currentPrefab == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int cost = 100;
|
||||
if (GoldSystem.Instance == null || !GoldSystem.Instance.TrySpend(cost))
|
||||
{
|
||||
Debug.Log($"金币不足,需要{cost}");
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 position = previewObject.transform.position;
|
||||
GameObject building = Instantiate(currentPrefab, position, Quaternion.identity);
|
||||
building.name = currentCharacterData != null
|
||||
? "兵营_" + currentCharacterData.characterName
|
||||
: "金矿";
|
||||
building.tag = "Friend";
|
||||
if (building.GetComponent<BuildingHealth>() == null)
|
||||
{
|
||||
building.AddComponent<BuildingHealth>();
|
||||
}
|
||||
|
||||
if (currentCharacterData != null)
|
||||
{
|
||||
Barracks barracks = building.GetComponent<Barracks>();
|
||||
if (barracks == null)
|
||||
{
|
||||
barracks = building.AddComponent<Barracks>();
|
||||
}
|
||||
|
||||
barracks.characterData = currentCharacterData;
|
||||
}
|
||||
else if (building.GetComponent<GoldMine>() == null)
|
||||
{
|
||||
building.AddComponent<GoldMine>();
|
||||
}
|
||||
|
||||
placedBuildings.Add(building);
|
||||
CancelPlacement();
|
||||
}
|
||||
|
||||
private void UpdatePreviewMaterial(bool valid)
|
||||
{
|
||||
Material material = valid ? previewMaterialValid : previewMaterialInvalid;
|
||||
if (material == null || previewObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (Renderer renderer in previewObject.GetComponentsInChildren<Renderer>())
|
||||
{
|
||||
renderer.sharedMaterial = material;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetCollidersEnabled(GameObject target, bool enabled)
|
||||
{
|
||||
foreach (Collider collider in target.GetComponentsInChildren<Collider>())
|
||||
{
|
||||
collider.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterExistingBuilding(GameObject building)
|
||||
{
|
||||
if (building != null && !placedBuildings.Contains(building))
|
||||
{
|
||||
placedBuildings.Add(building);
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelPlacement()
|
||||
{
|
||||
if (previewObject != null)
|
||||
{
|
||||
Destroy(previewObject);
|
||||
}
|
||||
|
||||
previewObject = null;
|
||||
currentPrefab = null;
|
||||
currentCharacterData = null;
|
||||
isPlacing = false;
|
||||
previewPositionValid = false;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: C31KvXn8U39bDHLWfJ9jSgBhWvoLhWw7Xvmn2WmpmrFDtWho+cg1kak=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,75 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 拆家版出兵管理:从城堡前方出兵点生成单位,消耗能量。
|
||||
/// 替代旧的召唤师身边召唤逻辑。
|
||||
/// </summary>
|
||||
public class CastleSpawnManager : MonoBehaviour
|
||||
{
|
||||
public static CastleSpawnManager Instance { get; private set; }
|
||||
|
||||
[Header("出兵点(城堡前方)")]
|
||||
public Transform blueSpawnPoint;
|
||||
public Transform redSpawnPoint;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance != null && Instance != this) { Destroy(gameObject); return; }
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
/// <summary>从指定阵营城堡出兵,消耗能量。teamId: 0=蓝, 1=红。</summary>
|
||||
public bool TrySpawn(CharacterData data, int teamId)
|
||||
{
|
||||
if (data == null || data.unitPrefab == null) return false;
|
||||
Transform spawnPoint = teamId == 0 ? blueSpawnPoint : redSpawnPoint;
|
||||
if (spawnPoint == null)
|
||||
{
|
||||
Debug.LogError($"找不到 teamId={teamId} 的出兵点");
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3 direction = spawnPoint.forward;
|
||||
direction.y = 0f;
|
||||
if (direction.sqrMagnitude < 0.001f) direction = Vector3.forward;
|
||||
direction.Normalize();
|
||||
|
||||
GameObject unit = Instantiate(
|
||||
data.unitPrefab,
|
||||
spawnPoint.position,
|
||||
Quaternion.LookRotation(direction, Vector3.up));
|
||||
|
||||
// 设置阵营
|
||||
UnitTeam unitTeam = unit.GetComponent<UnitTeam>();
|
||||
if (unitTeam != null)
|
||||
{
|
||||
unitTeam.teamId = teamId;
|
||||
unit.tag = teamId == 0 ? "Friend" : "Enemy";
|
||||
}
|
||||
|
||||
// 初始化属性(默认 1 级)
|
||||
UnitBase unitBase = unit.GetComponent<UnitBase>();
|
||||
if (unitBase != null)
|
||||
{
|
||||
PlayerCharacterData playerData = new PlayerCharacterData("castle_spawn", 1, 0);
|
||||
float hp = playerData.GetMaxHealth(data);
|
||||
float atk = playerData.GetAttackPower(data);
|
||||
float spd = playerData.GetMoveSpeed(data);
|
||||
unitBase.InitializeFromPlayerData(hp, atk, spd);
|
||||
|
||||
// 如果是敌人(teamId != 0),增大寻敌距离
|
||||
if (teamId != 0)
|
||||
{
|
||||
unitBase.detectionRange = 100f; // 从默认30增加到100
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"城堡出兵: {data.characterName} teamId={teamId} pos={spawnPoint.position}");
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CanAfford(CharacterData data)
|
||||
{
|
||||
return data != null && data.unitPrefab != null;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: Wysc5i6rUC+IV5FZ0/o3UMuAsbu+kExxLM4sa7XnkVGb+y85mKtxqMU=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,277 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class CrystalMineCapture : MonoBehaviour
|
||||
{
|
||||
[Header("争夺进度")]
|
||||
[Range(0f, 100f)] public float blueProgress = 50f;
|
||||
[Min(0f)] public float capturePerDamage = 1f;
|
||||
|
||||
[Tooltip("是否自动添加中立阵营(teamId=2)。拆家版关闭以避免单位自动锁敌水晶矿")]
|
||||
public bool autoSetNeutralTeam = true;
|
||||
|
||||
[Header("资源产出")]
|
||||
[Tooltip("占领后是否按固定间隔给所属阵营增加能量")]
|
||||
public bool producesMana = true;
|
||||
[Min(1f)] public float manaInterval = 8f;
|
||||
[Min(1)] public int manaAmount = 1;
|
||||
|
||||
// [SerializeField] private AdjustableGlowOrb glowOrb; // 已删除,视觉效果脚本未使用
|
||||
// [Tooltip("混沌裂缝传送门(随机出兵点),随争夺进度同步变色,可留空")]
|
||||
// [SerializeField] private RiftPortalVisual riftVisual; // 已删除,视觉效果脚本未使用
|
||||
[SerializeField] private Color neutralColor = Color.white;
|
||||
[SerializeField] private Color blueColor = new Color(0.1f, 0.65f, 1f, 1f);
|
||||
[SerializeField] private Color redColor = new Color(1f, 0.12f, 0.08f, 1f);
|
||||
|
||||
[Header("世界血条")]
|
||||
[Tooltip("血条相对模型渲染包围盒顶部的额外高度")]
|
||||
[Min(0f)] public float heightOffset = 1.1f;
|
||||
[Min(0.1f)] public float barWidth = 5f;
|
||||
|
||||
private float? barHeightCache;
|
||||
|
||||
private Canvas canvas;
|
||||
private RectTransform barRect;
|
||||
private Image blueFill;
|
||||
private Image redFill;
|
||||
private RectTransform marker;
|
||||
private UnitTeam unitTeam;
|
||||
private float manaTimer;
|
||||
private static Sprite roundedSprite;
|
||||
private static readonly int BaseColorId = Shader.PropertyToID("_Color");
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (autoSetNeutralTeam)
|
||||
{
|
||||
unitTeam = GetComponent<UnitTeam>();
|
||||
if (unitTeam == null)
|
||||
{
|
||||
unitTeam = gameObject.AddComponent<UnitTeam>();
|
||||
}
|
||||
unitTeam.teamId = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
unitTeam = GetComponent<UnitTeam>();
|
||||
}
|
||||
|
||||
// if (glowOrb == null)
|
||||
// {
|
||||
// glowOrb = GetComponentInChildren<AdjustableGlowOrb>(true);
|
||||
// }
|
||||
|
||||
// if (riftVisual == null)
|
||||
// {
|
||||
// riftVisual = GetComponentInChildren<RiftPortalVisual>(true);
|
||||
// }
|
||||
|
||||
CreateCaptureBar();
|
||||
RefreshVisuals();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// 强制重置光球颜色为初始状态
|
||||
// if (glowOrb != null)
|
||||
// {
|
||||
// glowOrb.SetGlowColor(neutralColor);
|
||||
// }
|
||||
RefreshVisuals();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
UpdateManaProduction();
|
||||
|
||||
if (barRect == null) return;
|
||||
|
||||
barRect.position = transform.position + Vector3.up * GetBarHeight();
|
||||
barRect.localScale = Vector3.one * (barWidth / 100f);
|
||||
|
||||
Camera camera = Camera.main;
|
||||
if (camera != null)
|
||||
{
|
||||
barRect.rotation = Quaternion.LookRotation(camera.transform.position - barRect.position, camera.transform.up);
|
||||
}
|
||||
}
|
||||
|
||||
// 血条高度 = 所有子 Renderer 包围盒顶部 + heightOffset。
|
||||
// 水晶矿模型根节点是 100 倍缩放,高度必须按世界包围盒算,否则血条会埋进模型内部被遮挡。
|
||||
private float GetBarHeight()
|
||||
{
|
||||
if (barHeightCache.HasValue) return barHeightCache.Value;
|
||||
|
||||
float top = 0f;
|
||||
Renderer[] renderers = GetComponentsInChildren<Renderer>();
|
||||
if (renderers.Length > 0)
|
||||
{
|
||||
Bounds bounds = renderers[0].bounds;
|
||||
for (int i = 1; i < renderers.Length; i++)
|
||||
{
|
||||
bounds.Encapsulate(renderers[i].bounds);
|
||||
}
|
||||
top = bounds.max.y;
|
||||
}
|
||||
barHeightCache = top - transform.position.y + heightOffset;
|
||||
return barHeightCache.Value;
|
||||
}
|
||||
|
||||
private void UpdateManaProduction()
|
||||
{
|
||||
if (!producesMana || unitTeam == null || (unitTeam.teamId != 0 && unitTeam.teamId != 1))
|
||||
{
|
||||
manaTimer = 0f;
|
||||
return;
|
||||
}
|
||||
|
||||
manaTimer += Time.deltaTime;
|
||||
while (manaTimer >= manaInterval)
|
||||
{
|
||||
manaTimer -= manaInterval;
|
||||
if (unitTeam.teamId == 0)
|
||||
{
|
||||
ManaSystem.Instance?.AddMana(manaAmount);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnemyCastleAI enemyAI = FindObjectOfType<EnemyCastleAI>();
|
||||
enemyAI?.AddMana(manaAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ReceiveCaptureDamage(float damage, GameObject attacker)
|
||||
{
|
||||
if (damage <= 0f || attacker == null) return false;
|
||||
|
||||
UnitTeam attackerTeam = attacker.GetComponentInParent<UnitTeam>();
|
||||
if (attackerTeam == null) return false;
|
||||
|
||||
float direction = attackerTeam.teamId == 0 ? 1f : -1f;
|
||||
blueProgress = Mathf.Clamp(blueProgress + direction * damage * capturePerDamage, 0f, 100f);
|
||||
RefreshVisuals();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetCaptureProgress(float value)
|
||||
{
|
||||
blueProgress = Mathf.Clamp(value, 0f, 100f);
|
||||
RefreshVisuals();
|
||||
}
|
||||
|
||||
private void RefreshVisuals()
|
||||
{
|
||||
if (blueFill == null || redFill == null) return;
|
||||
|
||||
float blue = blueProgress / 100f;
|
||||
blueFill.fillAmount = blue;
|
||||
redFill.fillAmount = 1f - blue;
|
||||
marker.anchorMin = new Vector2(blue, 0f);
|
||||
marker.anchorMax = new Vector2(blue, 1f);
|
||||
marker.anchoredPosition = Vector2.zero;
|
||||
marker.gameObject.SetActive(blueProgress > 0f && blueProgress < 100f);
|
||||
|
||||
if (unitTeam != null)
|
||||
{
|
||||
unitTeam.teamId = blueProgress >= 100f ? 0 : blueProgress <= 0f ? 1 : 2;
|
||||
}
|
||||
|
||||
// if (glowOrb != null)
|
||||
// {
|
||||
// Color color = blueProgress >= 100f ? blueColor : blueProgress <= 0f ? redColor : neutralColor;
|
||||
// glowOrb.SetGlowColor(color);
|
||||
// }
|
||||
|
||||
// if (riftVisual != null)
|
||||
// {
|
||||
// Color riftColor = blueProgress >= 100f ? blueColor : blueProgress <= 0f ? redColor : neutralColor;
|
||||
// riftVisual.SetRiftColor(riftColor);
|
||||
// }
|
||||
}
|
||||
|
||||
private void CreateCaptureBar()
|
||||
{
|
||||
GameObject root = new GameObject("CrystalCaptureBar", typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler));
|
||||
// 血条 Canvas 不要作为水晶矿的子对象,直接放在场景根目录避免被 100 倍缩放影响
|
||||
root.transform.parent = null;
|
||||
canvas = root.GetComponent<Canvas>();
|
||||
canvas.renderMode = RenderMode.WorldSpace;
|
||||
canvas.sortingOrder = 110;
|
||||
root.GetComponent<CanvasScaler>().dynamicPixelsPerUnit = 10f;
|
||||
barRect = root.GetComponent<RectTransform>();
|
||||
barRect.sizeDelta = new Vector2(100f, 16f);
|
||||
barRect.localScale = Vector3.one * (barWidth / 100f);
|
||||
|
||||
RectTransform row = CreateRow(root.transform, "CaptureBar", 100f, 14f);
|
||||
Image background = CreateImage(row, "Background", new Color(0.03f, 0.03f, 0.03f, 0.95f));
|
||||
SetFullRect(background.rectTransform);
|
||||
|
||||
blueFill = CreateImage(row, "BlueFill", blueColor);
|
||||
blueFill.type = Image.Type.Filled;
|
||||
blueFill.fillMethod = Image.FillMethod.Horizontal;
|
||||
blueFill.fillOrigin = 0;
|
||||
blueFill.rectTransform.anchorMin = new Vector2(0f, 0f);
|
||||
blueFill.rectTransform.anchorMax = new Vector2(1f, 1f);
|
||||
blueFill.rectTransform.offsetMin = new Vector2(2f, 2f);
|
||||
blueFill.rectTransform.offsetMax = new Vector2(-2f, -2f);
|
||||
|
||||
redFill = CreateImage(row, "RedFill", redColor);
|
||||
redFill.type = Image.Type.Filled;
|
||||
redFill.fillMethod = Image.FillMethod.Horizontal;
|
||||
redFill.fillOrigin = 1;
|
||||
redFill.rectTransform.anchorMin = new Vector2(0f, 0f);
|
||||
redFill.rectTransform.anchorMax = new Vector2(1f, 1f);
|
||||
redFill.rectTransform.offsetMin = new Vector2(2f, 2f);
|
||||
redFill.rectTransform.offsetMax = new Vector2(-2f, -2f);
|
||||
|
||||
GameObject markerObject = new GameObject("CenterMarker", typeof(RectTransform), typeof(Image));
|
||||
markerObject.transform.SetParent(row, false);
|
||||
marker = markerObject.GetComponent<RectTransform>();
|
||||
marker.sizeDelta = new Vector2(2f, 14f);
|
||||
marker.anchorMin = new Vector2(0.5f, 0f);
|
||||
marker.anchorMax = new Vector2(0.5f, 1f);
|
||||
marker.GetComponent<Image>().color = Color.white;
|
||||
}
|
||||
|
||||
private RectTransform CreateRow(Transform parent, string name, float width, float height)
|
||||
{
|
||||
GameObject rowObject = new GameObject(name, typeof(RectTransform));
|
||||
rowObject.transform.SetParent(parent, false);
|
||||
RectTransform rect = rowObject.GetComponent<RectTransform>();
|
||||
rect.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
rect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
rect.pivot = new Vector2(0.5f, 0.5f);
|
||||
rect.sizeDelta = new Vector2(width, height);
|
||||
return rect;
|
||||
}
|
||||
|
||||
private Image CreateImage(Transform parent, string name, Color color)
|
||||
{
|
||||
GameObject imageObject = new GameObject(name, typeof(RectTransform), typeof(Image));
|
||||
imageObject.transform.SetParent(parent, false);
|
||||
Image image = imageObject.GetComponent<Image>();
|
||||
image.sprite = RoundedSprite();
|
||||
image.color = color;
|
||||
return image;
|
||||
}
|
||||
|
||||
private void SetFullRect(RectTransform rect)
|
||||
{
|
||||
rect.anchorMin = Vector2.zero;
|
||||
rect.anchorMax = Vector2.one;
|
||||
rect.offsetMin = Vector2.zero;
|
||||
rect.offsetMax = Vector2.zero;
|
||||
}
|
||||
|
||||
private static Sprite RoundedSprite()
|
||||
{
|
||||
if (roundedSprite != null) return roundedSprite;
|
||||
Texture2D texture = new Texture2D(1, 1, TextureFormat.RGBA32, false);
|
||||
texture.SetPixel(0, 0, Color.white);
|
||||
texture.Apply();
|
||||
roundedSprite = Sprite.Create(texture, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f));
|
||||
roundedSprite.name = "CrystalCaptureBarSprite";
|
||||
return roundedSprite;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: Ci8f4Sz/WnrXjU/p2xyMiRtWkh/2zF5+zBmBE7FvT1PHEvOb80JVbxc=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,284 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 红方城堡自动出兵 AI:独立能量、三路目标评估、低费试探与高费推进。
|
||||
/// </summary>
|
||||
public class EnemyCastleAI : MonoBehaviour
|
||||
{
|
||||
[Header("AI 阵营")]
|
||||
[SerializeField] private int teamId = 1;
|
||||
[SerializeField] private int maxMana = 10;
|
||||
[SerializeField] private float manaRegenInterval = 3f;
|
||||
[SerializeField] private float decisionInterval = 1.2f;
|
||||
[SerializeField] private float minimumSpawnInterval = 1.4f;
|
||||
|
||||
[Header("三路目标")]
|
||||
[SerializeField] private float leftLaneX = -10f;
|
||||
[SerializeField] private float centerLaneX = 0f;
|
||||
[SerializeField] private float rightLaneX = 10f;
|
||||
[SerializeField] private float laneHalfWidth = 4f;
|
||||
[SerializeField] private float resourceThreatWeight = 2.5f;
|
||||
[SerializeField] private float enemyUnitWeight = 1.5f;
|
||||
[SerializeField] private float laneRotationWeight = 0.7f;
|
||||
|
||||
[Header("卡组轮转")]
|
||||
[SerializeField] private int visibleSlotCount = 4;
|
||||
[SerializeField] private string[] deckDataNames =
|
||||
{
|
||||
"人类士兵Data", "弓箭手Data", "盾卫Data", "精锐士兵Data",
|
||||
"法师Data", "狂暴狼人Data", "石巨人Data", "弓箭猎人Data"
|
||||
};
|
||||
[SerializeField] private CharacterData[] deck;
|
||||
|
||||
private readonly List<CharacterData> hand = new List<CharacterData>();
|
||||
private readonly Queue<CharacterData> drawQueue = new Queue<CharacterData>();
|
||||
private Transform redSpawnPoint;
|
||||
private AttackTargetController targetController;
|
||||
private float currentMana;
|
||||
private float manaTimer;
|
||||
private float decisionTimer;
|
||||
private float spawnTimer;
|
||||
private int lastLane = 1;
|
||||
private int consecutiveLaneSpawns;
|
||||
private bool initialized;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
redSpawnPoint = FindRedSpawnPoint();
|
||||
targetController = AttackTargetController.Instance;
|
||||
currentMana = maxMana;
|
||||
BuildDeck();
|
||||
BuildHand();
|
||||
initialized = redSpawnPoint != null && hand.Count > 0;
|
||||
if (!initialized)
|
||||
Debug.LogWarning("EnemyCastleAI 初始化失败:缺少红方出兵点或角色卡组。");
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!initialized) return;
|
||||
|
||||
manaTimer += Time.deltaTime;
|
||||
while (manaTimer >= manaRegenInterval)
|
||||
{
|
||||
manaTimer -= manaRegenInterval;
|
||||
currentMana = Mathf.Min(maxMana, currentMana + 1f);
|
||||
}
|
||||
|
||||
decisionTimer -= Time.deltaTime;
|
||||
spawnTimer -= Time.deltaTime;
|
||||
if (decisionTimer > 0f || spawnTimer > 0f) return;
|
||||
decisionTimer = decisionInterval;
|
||||
|
||||
int lane = ChooseLane();
|
||||
CharacterData card = ChooseCard(lane);
|
||||
if (card == null) return;
|
||||
if (Spawn(card, lane))
|
||||
{
|
||||
currentMana -= 1f;
|
||||
RotatePlayedCard(card);
|
||||
spawnTimer = minimumSpawnInterval;
|
||||
if (lane == lastLane) consecutiveLaneSpawns++;
|
||||
else consecutiveLaneSpawns = 1;
|
||||
lastLane = lane;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddMana(int amount)
|
||||
{
|
||||
if (amount <= 0) return;
|
||||
currentMana = Mathf.Min(maxMana, currentMana + amount);
|
||||
}
|
||||
|
||||
public int CurrentMana => Mathf.FloorToInt(currentMana);
|
||||
|
||||
public bool TrySpawnFromPortal(Vector3 spawnPosition, Quaternion spawnRotation)
|
||||
{
|
||||
if (!initialized) return false;
|
||||
|
||||
List<CharacterData> affordable = new List<CharacterData>();
|
||||
foreach (CharacterData card in hand)
|
||||
{
|
||||
if (card != null && card.unitPrefab != null)
|
||||
affordable.Add(card);
|
||||
}
|
||||
|
||||
if (affordable.Count == 0) return false;
|
||||
|
||||
CharacterData selected = affordable[Random.Range(0, affordable.Count)];
|
||||
if (!SpawnAt(selected, spawnPosition, spawnRotation, teamId)) return false;
|
||||
|
||||
currentMana -= 1f;
|
||||
RotatePlayedCard(selected);
|
||||
return true;
|
||||
}
|
||||
|
||||
private CharacterData SelectWeightedCard(List<CharacterData> cards)
|
||||
{
|
||||
return cards == null || cards.Count == 0 ? null : cards[Random.Range(0, cards.Count)];
|
||||
}
|
||||
|
||||
private int ChooseLane()
|
||||
{
|
||||
float left = ScoreLane(leftLaneX, 0);
|
||||
float center = ScoreLane(centerLaneX, 1);
|
||||
float right = ScoreLane(rightLaneX, 2);
|
||||
|
||||
if (consecutiveLaneSpawns >= 2)
|
||||
{
|
||||
if (lastLane == 0) left -= 3f;
|
||||
if (lastLane == 1) center -= 3f;
|
||||
if (lastLane == 2) right -= 3f;
|
||||
}
|
||||
|
||||
float best = Mathf.Max(left, Mathf.Max(center, right));
|
||||
if (Mathf.Approximately(best, left)) return 0;
|
||||
if (Mathf.Approximately(best, right)) return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
private float ScoreLane(float laneX, int lane)
|
||||
{
|
||||
float score = 1f;
|
||||
score += lane == 1 ? 0.8f : 0f;
|
||||
score += lane == lastLane ? laneRotationWeight : 0f;
|
||||
|
||||
foreach (var unit in FindObjectsOfType<UnitTeam>())
|
||||
{
|
||||
if (unit == null || unit.teamId != 0) continue;
|
||||
Vector3 p = unit.transform.position;
|
||||
if (Mathf.Abs(p.x - laneX) <= laneHalfWidth)
|
||||
score += enemyUnitWeight;
|
||||
}
|
||||
|
||||
foreach (var mine in FindObjectsOfType<CrystalMineCapture>())
|
||||
{
|
||||
if (mine == null) continue;
|
||||
Vector3 p = mine.transform.position;
|
||||
if (Mathf.Abs(p.x - laneX) > laneHalfWidth * 1.8f) continue;
|
||||
UnitTeam team = mine.GetComponent<UnitTeam>();
|
||||
if (team == null || team.teamId != teamId)
|
||||
score += resourceThreatWeight;
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
private CharacterData ChooseCard(int lane)
|
||||
{
|
||||
CharacterData best = null;
|
||||
float bestScore = float.NegativeInfinity;
|
||||
foreach (var card in hand)
|
||||
{
|
||||
if (card == null || card.unitPrefab == null) continue;
|
||||
float score = Random.Range(0f, 1f);
|
||||
if (score > bestScore)
|
||||
{
|
||||
bestScore = score;
|
||||
best = card;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
private void BuildDeck()
|
||||
{
|
||||
if (deck != null && deck.Length > 0) return;
|
||||
|
||||
var loadedDeck = new List<CharacterData>();
|
||||
foreach (string dataName in deckDataNames)
|
||||
{
|
||||
CharacterData data = Resources.Load<CharacterData>("Data/" + dataName);
|
||||
if (data == null)
|
||||
{
|
||||
Debug.LogWarning($"敌方卡组缺少角色数据: Resources/Data/{dataName}.asset");
|
||||
continue;
|
||||
}
|
||||
loadedDeck.Add(data);
|
||||
}
|
||||
deck = loadedDeck.ToArray();
|
||||
}
|
||||
|
||||
private void BuildHand()
|
||||
{
|
||||
hand.Clear();
|
||||
drawQueue.Clear();
|
||||
if (deck == null) return;
|
||||
|
||||
int handCount = Mathf.Min(visibleSlotCount, deck.Length);
|
||||
for (int i = 0; i < handCount; i++)
|
||||
hand.Add(deck[i]);
|
||||
for (int i = handCount; i < deck.Length; i++)
|
||||
drawQueue.Enqueue(deck[i]);
|
||||
}
|
||||
|
||||
private void RotatePlayedCard(CharacterData playedCard)
|
||||
{
|
||||
int handIndex = hand.IndexOf(playedCard);
|
||||
if (handIndex < 0 || drawQueue.Count == 0) return;
|
||||
|
||||
hand[handIndex] = drawQueue.Dequeue();
|
||||
drawQueue.Enqueue(playedCard);
|
||||
}
|
||||
|
||||
private bool SpawnAt(CharacterData data, Vector3 position, Quaternion rotation, int spawnTeamId)
|
||||
{
|
||||
GameObject unit = Instantiate(data.unitPrefab, position, rotation);
|
||||
UnitTeam team = unit.GetComponent<UnitTeam>();
|
||||
if (team != null)
|
||||
{
|
||||
team.teamId = spawnTeamId;
|
||||
unit.tag = spawnTeamId == 0 ? "Friend" : "Enemy";
|
||||
}
|
||||
|
||||
UnitBase unitBase = unit.GetComponent<UnitBase>();
|
||||
if (unitBase != null)
|
||||
{
|
||||
unitBase.InitializeFromPlayerData(data.GetMaxHealth(1), data.GetAttackPower(1), data.GetMoveSpeed(1));
|
||||
|
||||
// 如果是敌人(teamId != 0),增大寻敌距离
|
||||
if (spawnTeamId != 0)
|
||||
{
|
||||
unitBase.detectionRange = 100f; // 从默认30增加到100
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool Spawn(CharacterData data, int lane)
|
||||
{
|
||||
if (!SpawnAt(data, redSpawnPoint.position, redSpawnPoint.rotation, teamId)) return false;
|
||||
|
||||
if (targetController != null)
|
||||
{
|
||||
targetController.redTarget = FindLaneTarget(lane);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private GameObject FindLaneTarget(int lane)
|
||||
{
|
||||
float x = lane == 0 ? leftLaneX : lane == 2 ? rightLaneX : centerLaneX;
|
||||
GameObject best = null;
|
||||
float bestDistance = float.PositiveInfinity;
|
||||
foreach (var mine in FindObjectsOfType<CrystalMineCapture>())
|
||||
{
|
||||
if (Mathf.Abs(mine.transform.position.x - x) < laneHalfWidth * 2f)
|
||||
{
|
||||
float d = Mathf.Abs(mine.transform.position.z - redSpawnPoint.position.z);
|
||||
if (d < bestDistance) { bestDistance = d; best = mine.gameObject; }
|
||||
}
|
||||
}
|
||||
return best != null ? best : targetController?.GetEnemyCastleOfTeam(teamId);
|
||||
}
|
||||
|
||||
private Transform FindRedSpawnPoint()
|
||||
{
|
||||
var manager = GetComponent<CastleSpawnManager>();
|
||||
if (manager != null && manager.redSpawnPoint != null) return manager.redSpawnPoint;
|
||||
var castles = GameObject.Find("红色城堡");
|
||||
return castles != null ? castles.transform.Find("出兵点") : null;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: Di4e5COsW3MaOIKjAZpkNB3DV96stk4sKbaXXg7lgL4M9IOQyMJld6Y=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,78 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 金矿建筑,定时产出金币
|
||||
/// </summary>
|
||||
public class GoldMine : MonoBehaviour
|
||||
{
|
||||
[Header("金币产出")]
|
||||
[Tooltip("每次产出的金币数量")]
|
||||
[SerializeField] private int goldPerProduction = 50;
|
||||
|
||||
[Tooltip("产出间隔(秒)")]
|
||||
[SerializeField] private float productionInterval = 5f;
|
||||
|
||||
[Header("可选:血条和进度条")]
|
||||
[SerializeField] private WorldHealthBar healthBar;
|
||||
|
||||
private float productionTimer = 0f;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// 如果没有手动指定,尝试自动获取
|
||||
if (healthBar == null)
|
||||
{
|
||||
healthBar = GetComponent<WorldHealthBar>();
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// 初始化进度条(使用能量条显示产出进度)
|
||||
if (healthBar != null)
|
||||
{
|
||||
healthBar.maxEnergy = 100f;
|
||||
healthBar.currentEnergy = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (GoldManager.Instance == null) return;
|
||||
|
||||
productionTimer += Time.deltaTime;
|
||||
|
||||
// 更新进度条
|
||||
if (healthBar != null)
|
||||
{
|
||||
float progress = Mathf.Clamp01(productionTimer / productionInterval);
|
||||
healthBar.currentEnergy = progress * 100f;
|
||||
}
|
||||
|
||||
// 达到产出时间
|
||||
if (productionTimer >= productionInterval)
|
||||
{
|
||||
ProduceGold();
|
||||
productionTimer = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
private void ProduceGold()
|
||||
{
|
||||
if (GoldManager.Instance != null)
|
||||
{
|
||||
GoldManager.Instance.AddGold(goldPerProduction);
|
||||
Debug.Log($"{gameObject.name} 产出金币 +{goldPerProduction}");
|
||||
|
||||
// 可以在这里播放特效和音效
|
||||
// TODO: 添加金币产出特效
|
||||
}
|
||||
}
|
||||
|
||||
// 在编辑器中显示信息
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
Gizmos.color = Color.yellow;
|
||||
Gizmos.DrawWireSphere(transform.position + Vector3.up * 2f, 0.5f);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: DykfvC7+VnysnFVe0RuuhqYblOX8b3TqKpWkys/vBAvo9QxqFltLb0g=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -13,6 +13,13 @@ public class EliteSoldierSkill : UnitSkill
|
||||
[Min(0f)]
|
||||
public float skillAnimationDuration = 2.22f;
|
||||
|
||||
[Header("特效")]
|
||||
public GameObject groundCrackEffectPrefab;
|
||||
[Min(0f)]
|
||||
public float groundCrackForwardDistance = 1.2f;
|
||||
[Min(0f)]
|
||||
public float groundCrackHeightOffset = 0.05f;
|
||||
|
||||
private bool isSkillReady;
|
||||
|
||||
public override void ReleaseSkill()
|
||||
@@ -35,6 +42,24 @@ public class EliteSoldierSkill : UnitSkill
|
||||
return;
|
||||
}
|
||||
|
||||
if (groundCrackEffectPrefab != null)
|
||||
{
|
||||
Vector3 effectPosition = unit.transform.position
|
||||
+ unit.transform.forward * groundCrackForwardDistance;
|
||||
effectPosition.y += groundCrackHeightOffset;
|
||||
|
||||
GameObject effectObject = Instantiate(
|
||||
groundCrackEffectPrefab,
|
||||
effectPosition,
|
||||
groundCrackEffectPrefab.transform.rotation);
|
||||
|
||||
ShockwaveRing shockwave = effectObject.GetComponent<ShockwaveRing>();
|
||||
if (shockwave != null)
|
||||
{
|
||||
shockwave.Play();
|
||||
}
|
||||
}
|
||||
|
||||
unit.ApplyAreaSkillDamage(skillRadius, skillDamage, false);
|
||||
isSkillReady = false;
|
||||
}
|
||||
|
||||
@@ -46,14 +46,10 @@ public class StoneGolemSkill : UnitSkill
|
||||
{
|
||||
Vector3 effectPosition = unit.transform.position;
|
||||
var effectObj = Instantiate(shockwaveEffectPrefab, effectPosition, shockwaveEffectPrefab.transform.rotation);
|
||||
|
||||
// 可选:动态配置特效参数(不配置则使用Prefab默认值)
|
||||
var effect = effectObj.GetComponent<ShockwaveEffect>();
|
||||
if (effect != null)
|
||||
ShockwaveRing shockwave = effectObj.GetComponent<ShockwaveRing>();
|
||||
if (shockwave != null)
|
||||
{
|
||||
// 根据技能范围动态设置扩散半径
|
||||
effect.overrideRadius = skillRadius;
|
||||
// 可以设置颜色,例如:effect.overrideColor = new Color(1f, 0.8f, 0.2f, 1f);
|
||||
shockwave.Play();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -122,11 +122,9 @@ public class Projectile : MonoBehaviour
|
||||
}
|
||||
|
||||
UnitBase targetUnit = hitObject.GetComponentInParent<UnitBase>();
|
||||
CrystalMineCapture crystalMine = hitObject.GetComponentInParent<CrystalMineCapture>();
|
||||
BuildingHealth targetBuilding = hitObject.GetComponentInParent<BuildingHealth>();
|
||||
WorldHealthBar targetHealthBar = hitObject.GetComponentInParent<WorldHealthBar>();
|
||||
|
||||
if (targetUnit == null && crystalMine == null && targetBuilding == null && targetHealthBar == null)
|
||||
if (targetUnit == null && targetHealthBar == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -137,14 +135,6 @@ public class Projectile : MonoBehaviour
|
||||
{
|
||||
targetUnit.ReceiveDamage(damage, owner);
|
||||
}
|
||||
else if (crystalMine != null)
|
||||
{
|
||||
crystalMine.ReceiveCaptureDamage(damage, owner);
|
||||
}
|
||||
else if (targetBuilding != null)
|
||||
{
|
||||
targetBuilding.ReceiveDamage(damage, owner);
|
||||
}
|
||||
else if (targetHealthBar != null)
|
||||
{
|
||||
// 召唤师等特殊单位(有 WorldHealthBar 但没有 UnitBase)
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
using UnityEngine;
|
||||
|
||||
public enum CharacterRarity
|
||||
{
|
||||
Blue = 0,
|
||||
Orange = 1,
|
||||
Purple = 2,
|
||||
Red = 3
|
||||
}
|
||||
|
||||
[CreateAssetMenu(fileName = "NewCharacterData", menuName = "召唤之战/角色数据")]
|
||||
public class CharacterData : ScriptableObject
|
||||
{
|
||||
[Header("基础信息")]
|
||||
public string characterId = "unknown";
|
||||
public string characterName = "未命名角色";
|
||||
public CharacterRarity rarity = CharacterRarity.Blue;
|
||||
|
||||
[TextArea(2, 4)]
|
||||
public string description = "";
|
||||
|
||||
@@ -2,20 +2,22 @@ using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 部署网格的几何参数与坐标换算。
|
||||
/// 阵型编排场景和战斗场景共用同一份参数,保证两边的格位完全对齐。
|
||||
/// 网格与场景里用于标记布阵区域的那个 Plane 完全重合:
|
||||
/// Plane 世界范围 X -5.75..5.75、Z -15.6..-4.4,中心 (0, ?, -10)。
|
||||
/// 4 列 × 4 行,正好铺满这块区域;整体位于 NavMesh 覆盖范围内。
|
||||
/// </summary>
|
||||
public static class DeployGrid
|
||||
{
|
||||
public const int Cols = 6;
|
||||
public const int Rows = 5;
|
||||
public const float ColStep = 2.4f; // 列间距改为2.4,让网格更紧凑,避免最边缘格子太靠外
|
||||
public const float RowStep = 2.8f; // 行间距保持2.8
|
||||
public const float BackZ = -15.0f; // 最靠后一排的中心 Z(调整到靠近摄像机的底部区域)
|
||||
public const float CellWidth = 2.5f;
|
||||
public const float CellDepth = 2.5f; // 格子深度改为2.5,与宽度相同,形成正方形
|
||||
public const int Cols = 4;
|
||||
public const int Rows = 4;
|
||||
public const float ColStep = 2.875f; // 11.5 / 4
|
||||
public const float RowStep = 2.8f; // 11.2 / 4
|
||||
public const float BackZ = -14.2f; // 第 0 排(最靠近镜头)中心 Z = -10 - 1.5*2.8
|
||||
public const float CellWidth = 2.815f; // 比间距略小,留出缝,看得出是格子
|
||||
public const float CellDepth = 2.74f;
|
||||
public const float CellHeight = 0.03f;
|
||||
public const float GridY = 0.12f; // 格位可视块的中心高度
|
||||
public const float UnitY = 0.16f; // 单位落点高度(与 NavMesh 高度一致)
|
||||
public const float GridY = 0.115f; // 格位可视块中心高度(贴在布阵平面之上)
|
||||
public const float UnitY = 0.10f; // 单位落点高度(与烘焙后的 NavMesh 高度一致)
|
||||
|
||||
public const int CellCount = Cols * Rows;
|
||||
|
||||
@@ -34,7 +36,23 @@ public static class DeployGrid
|
||||
return new Vector3(x, UnitY, z);
|
||||
}
|
||||
|
||||
/// <summary>把地面上的世界坐标吸附到最近格位;不在网格范围内返回 -1。</summary>
|
||||
/// <summary>整个网格的中心(可视块高度)。</summary>
|
||||
public static Vector3 GridCenter
|
||||
{
|
||||
get
|
||||
{
|
||||
float z = BackZ + (Rows - 1) * RowStep * 0.5f;
|
||||
return new Vector3(0f, GridY, z);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>网格在 X 方向的宽度。</summary>
|
||||
public static float GridWidth => Cols * ColStep;
|
||||
|
||||
/// <summary>网格在 Z 方向的深度。</summary>
|
||||
public static float GridDepth => Rows * RowStep;
|
||||
|
||||
/// <summary>把地面坐标吸附到最近格位;不在网格范围内返回 -1。</summary>
|
||||
public static int SnapToCell(Vector3 world)
|
||||
{
|
||||
int c = Mathf.RoundToInt(world.x / ColStep + (Cols - 1) * 0.5f);
|
||||
@@ -50,6 +68,29 @@ public static class DeployGrid
|
||||
return ToIndex(r, c);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 宽松吸附:超出网格时夹到最近格位,只要离网格边缘不超过 tolerance 个格子就算命中。
|
||||
/// 让玩家在网格边缘附近松手也能放下单位。
|
||||
/// </summary>
|
||||
public static int SnapToCellClamped(Vector3 world, float tolerance = 0.9f)
|
||||
{
|
||||
int c = Mathf.RoundToInt(world.x / ColStep + (Cols - 1) * 0.5f);
|
||||
int r = Mathf.RoundToInt((world.z - BackZ) / RowStep);
|
||||
|
||||
int clampedC = Mathf.Clamp(c, 0, Cols - 1);
|
||||
int clampedR = Mathf.Clamp(r, 0, Rows - 1);
|
||||
|
||||
// 超出网格多少(以格为单位)
|
||||
int overC = c < 0 ? -c : (c >= Cols ? c - (Cols - 1) : 0);
|
||||
int overR = r < 0 ? -r : (r >= Rows ? r - (Rows - 1) : 0);
|
||||
if (overC > tolerance || overR > tolerance)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ToIndex(clampedR, clampedC);
|
||||
}
|
||||
|
||||
/// <summary>把一组单位在网格宽度内均匀铺开,返回列号。</summary>
|
||||
public static int SpreadColumn(int indexInGroup, int groupCount)
|
||||
{
|
||||
@@ -60,7 +101,7 @@ public static class DeployGrid
|
||||
return Mathf.RoundToInt(step * (indexInGroup + 1));
|
||||
}
|
||||
|
||||
/// <summary>默认阵型格位:近战在最前排(靠近敌人),远程在最后排。</summary>
|
||||
/// <summary>默认阵型格位:近战在最靠敌方的一排,远程在最后排。</summary>
|
||||
public static int DefaultCell(bool isMelee, int indexInGroup, int groupCount)
|
||||
{
|
||||
int row = isMelee ? Rows - 1 : 0;
|
||||
|
||||
@@ -81,13 +81,28 @@ public class StatusEffectController : MonoBehaviour
|
||||
|
||||
Bounds bounds = new Bounds(transform.position, Vector3.zero);
|
||||
Renderer[] renderers = GetComponentsInChildren<Renderer>(true);
|
||||
if (renderers.Length > 0)
|
||||
bool hasRenderer = false;
|
||||
foreach (Renderer renderer in renderers)
|
||||
{
|
||||
bounds = renderers[0].bounds;
|
||||
for (int i = 1; i < renderers.Length; i++)
|
||||
if (stunIndicator != null && renderer.transform.IsChildOf(stunIndicator.transform))
|
||||
{
|
||||
bounds.Encapsulate(renderers[i].bounds);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hasRenderer)
|
||||
{
|
||||
bounds = renderer.bounds;
|
||||
hasRenderer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bounds.Encapsulate(renderer.bounds);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasRenderer)
|
||||
{
|
||||
bounds = new Bounds(transform.position, Vector3.zero);
|
||||
}
|
||||
|
||||
indicatorTransform.position = new Vector3(
|
||||
|
||||
@@ -126,11 +126,6 @@ public class MainCharacterDebugMovement : MonoBehaviour
|
||||
continue;
|
||||
}
|
||||
|
||||
if (candidate.GetComponentInParent<BuildingHealth>() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 主建筑按名称优先匹配;找不到时退回第一个己方建筑
|
||||
if (candidate.name.Contains("主要") || candidate.name.Contains("基地"))
|
||||
{
|
||||
|
||||
@@ -76,13 +76,17 @@ public class UnitBase : MonoBehaviour
|
||||
private bool summonerAttackEnabled = true;
|
||||
|
||||
[Header("无目标回位")]
|
||||
[Tooltip("开启后,当前没有敌方单位时返回生成时的初始格位;不限制正常追击距离。")]
|
||||
[Tooltip("开启后,当前没有敌方单位时返回生成时的初始格位。")]
|
||||
public bool returnToAnchorWhenIdle = false;
|
||||
[Min(0.1f)]
|
||||
public float anchorArrivalDistance = 0.35f;
|
||||
private Vector3 anchorPosition;
|
||||
private bool anchorInitialized;
|
||||
|
||||
[Header("阵位守护")]
|
||||
[Tooltip("开启后,只打「离自己阵位不超过 寻敌视野 detectionRange」的敌人,避免一路推到很远的地方。")]
|
||||
public bool useAnchorLeash = false;
|
||||
|
||||
//角色状态
|
||||
private State state = State.Alert;
|
||||
|
||||
@@ -112,6 +116,8 @@ public class UnitBase : MonoBehaviour
|
||||
private float attackSpeedMultiplier = 1f;
|
||||
private UnitSkill unitSkill;
|
||||
private System.Action skillFinishedCallback;
|
||||
private float skillElapsedTime;
|
||||
private float skillTimeout;
|
||||
|
||||
|
||||
//状态枚举
|
||||
@@ -183,7 +189,7 @@ public class UnitBase : MonoBehaviour
|
||||
navAgent.speed = speed;
|
||||
navAgent.angularSpeed = 120f;
|
||||
navAgent.acceleration = 8f;
|
||||
navAgent.stoppingDistance = attackRange * 0.95f; // 接近攻击范围边缘时停止
|
||||
navAgent.stoppingDistance = NormalStoppingDistance; // 接近攻击范围边缘时停止
|
||||
navAgent.autoBraking = true;
|
||||
|
||||
// NavMesh 使用烘焙平面的高度,不能根据动画帧中的 Renderer 包围盒推算 baseOffset。
|
||||
@@ -287,6 +293,13 @@ public class UnitBase : MonoBehaviour
|
||||
// Attack 状态在上方单独处理,因此不会被这里打断或切换目标。
|
||||
target = FindTarget();
|
||||
|
||||
// 阵位守护:目标离自己阵位超过寻敌视野(detectionRange)就不追了,留在阵位附近
|
||||
if (target != null && useAnchorLeash && anchorInitialized
|
||||
&& IsBeyondLeash(target.transform.position, detectionRange))
|
||||
{
|
||||
target = null;
|
||||
}
|
||||
|
||||
if (target != null)
|
||||
{
|
||||
// 召唤师模式:不主动追击,站定且攻击开关开启时才攻击射程内目标。
|
||||
@@ -374,6 +387,11 @@ public class UnitBase : MonoBehaviour
|
||||
|
||||
public void ApplyStun(float duration)
|
||||
{
|
||||
if (duration <= 0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureStatusEffectController().ApplyStun(duration);
|
||||
}
|
||||
|
||||
@@ -455,6 +473,20 @@ public class UnitBase : MonoBehaviour
|
||||
return Vector3.Distance(current, anchor) <= anchorArrivalDistance;
|
||||
}
|
||||
|
||||
/// <summary>某个世界坐标是否离锚点超过了指定距离(只算水平距离)。</summary>
|
||||
private bool IsBeyondLeash(Vector3 worldPosition, float maxDistance)
|
||||
{
|
||||
if (!anchorInitialized) return false;
|
||||
Vector3 anchor = anchorPosition;
|
||||
anchor.y = 0f;
|
||||
Vector3 point = worldPosition;
|
||||
point.y = 0f;
|
||||
return Vector3.Distance(anchor, point) > maxDistance;
|
||||
}
|
||||
|
||||
/// <summary>追击/接敌时用的停靠距离(贴着攻击范围边缘停下)。</summary>
|
||||
private float NormalStoppingDistance => Mathf.Max(0f, attackRange * 0.95f);
|
||||
|
||||
/// <summary>
|
||||
/// 重置锚点位置到当前位置(用于复活等场景)
|
||||
/// </summary>
|
||||
@@ -468,11 +500,7 @@ public class UnitBase : MonoBehaviour
|
||||
{
|
||||
if (navAgent == null || !anchorInitialized)
|
||||
{
|
||||
if (!summonerMode)
|
||||
{
|
||||
animator.SetInteger("speed", 0);
|
||||
animator.speed = 1f; // 重置动画播放速度
|
||||
}
|
||||
RestoreIdleSpeed();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -483,11 +511,7 @@ public class UnitBase : MonoBehaviour
|
||||
|
||||
if (!navAgent.isOnNavMesh)
|
||||
{
|
||||
if (!summonerMode)
|
||||
{
|
||||
animator.SetInteger("speed", 0);
|
||||
animator.speed = 1f; // 重置动画播放速度
|
||||
}
|
||||
RestoreIdleSpeed();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -497,22 +521,41 @@ public class UnitBase : MonoBehaviour
|
||||
navAgent.ResetPath();
|
||||
transform.position = new Vector3(anchorPosition.x, transform.position.y, anchorPosition.z);
|
||||
navAgent.nextPosition = transform.position;
|
||||
if (!summonerMode)
|
||||
{
|
||||
animator.SetInteger("speed", 0);
|
||||
animator.speed = 1f; // 重置动画播放速度
|
||||
}
|
||||
RestoreIdleSpeed();
|
||||
return;
|
||||
}
|
||||
|
||||
navAgent.isStopped = false;
|
||||
// 回位必须贴到锚点:攻击用的停靠距离会把 agent 挡在半路(远程角色尤其明显)
|
||||
navAgent.stoppingDistance = 0f;
|
||||
if (Time.time >= nextPathUpdateTime)
|
||||
{
|
||||
navAgent.SetDestination(anchorPosition);
|
||||
nextPathUpdateTime = Time.time + PathUpdateInterval;
|
||||
}
|
||||
animator.SetInteger("speed", navAgent.velocity.sqrMagnitude > 0.01f ? 1 : 0);
|
||||
animator.speed = 1f; // 确保移动时动画速度正常
|
||||
|
||||
// 用正常速度走回格位
|
||||
navAgent.speed = speed;
|
||||
if (!summonerMode)
|
||||
{
|
||||
animator.SetInteger("speed", navAgent.velocity.sqrMagnitude > 0.01f ? 1 : 0);
|
||||
animator.speed = 1f; // 确保走路动画速度正常
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>回位结束或无法寻路时,把速度和动画恢复成正常站定状态。</summary>
|
||||
private void RestoreIdleSpeed()
|
||||
{
|
||||
if (navAgent != null && navAgent.enabled)
|
||||
{
|
||||
navAgent.speed = speed;
|
||||
navAgent.stoppingDistance = NormalStoppingDistance;
|
||||
}
|
||||
if (!summonerMode && animator != null)
|
||||
{
|
||||
animator.SetInteger("speed", 0);
|
||||
animator.speed = 1f;
|
||||
}
|
||||
}
|
||||
|
||||
//目标决策:只寻找 detectionRange 内的敌方战斗单位;范围内没有敌人时原地待机或回到锚点。
|
||||
@@ -837,21 +880,6 @@ public class UnitBase : MonoBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
CrystalMineCapture targetCrystalMine = opponent.GetComponentInParent<CrystalMineCapture>();
|
||||
if (targetCrystalMine != null && targetCrystalMine.ReceiveCaptureDamage(attackPower, gameObject))
|
||||
{
|
||||
RegisterAttackHit();
|
||||
return;
|
||||
}
|
||||
|
||||
BuildingHealth targetBuilding = opponent.GetComponentInParent<BuildingHealth>();
|
||||
if (targetBuilding != null && targetBuilding.ReceiveDamage(attackPower, gameObject))
|
||||
{
|
||||
RegisterAttackHit();
|
||||
return;
|
||||
}
|
||||
|
||||
// 召唤师等特殊单位(有 WorldHealthBar 但没有 UnitBase)
|
||||
WorldHealthBar targetHealthBar = opponent.GetComponentInParent<WorldHealthBar>();
|
||||
if (targetHealthBar != null)
|
||||
{
|
||||
@@ -871,18 +899,6 @@ public class UnitBase : MonoBehaviour
|
||||
UnitBase targetUnit = target.GetComponentInParent<UnitBase>();
|
||||
bool hit = targetUnit != null && targetUnit.ReceiveDamage(damage, gameObject);
|
||||
|
||||
if (!hit)
|
||||
{
|
||||
CrystalMineCapture targetCrystalMine = target.GetComponentInParent<CrystalMineCapture>();
|
||||
hit = targetCrystalMine != null && targetCrystalMine.ReceiveCaptureDamage(damage, gameObject);
|
||||
}
|
||||
|
||||
if (!hit)
|
||||
{
|
||||
BuildingHealth targetBuilding = target.GetComponentInParent<BuildingHealth>();
|
||||
hit = targetBuilding != null && targetBuilding.ReceiveDamage(damage, gameObject);
|
||||
}
|
||||
|
||||
if (!hit)
|
||||
{
|
||||
return;
|
||||
@@ -937,22 +953,9 @@ public class UnitBase : MonoBehaviour
|
||||
}
|
||||
|
||||
UnitBase targetUnit = opponent.GetComponentInParent<UnitBase>();
|
||||
BuildingHealth targetBuilding = opponent.GetComponentInParent<BuildingHealth>();
|
||||
WorldHealthBar healthBar = null;
|
||||
|
||||
if (targetUnit != null)
|
||||
{
|
||||
healthBar = targetUnit.GetComponent<WorldHealthBar>();
|
||||
}
|
||||
else if (targetBuilding != null)
|
||||
{
|
||||
healthBar = targetBuilding.GetComponent<WorldHealthBar>();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 召唤师等特殊单位(有 WorldHealthBar 但没有 UnitBase)
|
||||
healthBar = opponent.GetComponentInParent<WorldHealthBar>();
|
||||
}
|
||||
WorldHealthBar healthBar = targetUnit != null
|
||||
? targetUnit.GetComponent<WorldHealthBar>()
|
||||
: opponent.GetComponentInParent<WorldHealthBar>();
|
||||
|
||||
if (healthBar == null || !hitHealthBars.Add(healthBar))
|
||||
{
|
||||
@@ -963,13 +966,8 @@ public class UnitBase : MonoBehaviour
|
||||
{
|
||||
targetUnit.ReceiveDamage(damage, gameObject);
|
||||
}
|
||||
else if (targetBuilding != null)
|
||||
else
|
||||
{
|
||||
targetBuilding.ReceiveDamage(damage, gameObject);
|
||||
}
|
||||
else if (healthBar != null)
|
||||
{
|
||||
// 召唤师等特殊单位
|
||||
healthBar.TakeDamage(damage, gameObject);
|
||||
}
|
||||
}
|
||||
@@ -999,6 +997,7 @@ public class UnitBase : MonoBehaviour
|
||||
// 查找所有带 UnitTeam 的对象(包括单位和召唤师)
|
||||
UnitTeam[] allTeams = FindObjectsOfType<UnitTeam>();
|
||||
HashSet<UnitBase> hitUnits = new HashSet<UnitBase>();
|
||||
HashSet<StatusEffectController> hitStatusEffects = new HashSet<StatusEffectController>();
|
||||
|
||||
foreach (UnitTeam targetTeam in allTeams)
|
||||
{
|
||||
@@ -1031,7 +1030,7 @@ public class UnitBase : MonoBehaviour
|
||||
|
||||
// 召唤师等特殊单位(有 StatusEffectController 但没有 UnitBase)
|
||||
StatusEffectController statusEffect = opponent.GetComponentInParent<StatusEffectController>();
|
||||
if (statusEffect != null)
|
||||
if (statusEffect != null && hitStatusEffects.Add(statusEffect))
|
||||
{
|
||||
statusEffect.ApplyStun(duration);
|
||||
}
|
||||
@@ -1129,6 +1128,11 @@ public class UnitBase : MonoBehaviour
|
||||
|
||||
skillFinishedCallback = onFinished;
|
||||
isPlayingSkill = true;
|
||||
skillElapsedTime = 0f;
|
||||
float animationDuration = GetSkillAnimationDuration();
|
||||
skillTimeout = targetDuration > 0f
|
||||
? targetDuration + 0.5f
|
||||
: Mathf.Max(animationDuration + 0.5f, 2f);
|
||||
state = State.Skill;
|
||||
animator.speed = GetSkillAnimationSpeed(targetDuration);
|
||||
animator.SetInteger("speed", 0);
|
||||
@@ -1145,13 +1149,23 @@ public class UnitBase : MonoBehaviour
|
||||
|
||||
private void CheckSkillAnimationFinished()
|
||||
{
|
||||
if (!isPlayingSkill)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
skillElapsedTime += Time.deltaTime;
|
||||
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
|
||||
if (!stateInfo.IsName("skill") || stateInfo.normalizedTime < 1f)
|
||||
bool animationFinished = stateInfo.IsName("skill") && stateInfo.normalizedTime >= 1f;
|
||||
bool timedOut = skillElapsedTime >= skillTimeout;
|
||||
if (!animationFinished && !timedOut)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
isPlayingSkill = false;
|
||||
skillElapsedTime = 0f;
|
||||
skillTimeout = 0f;
|
||||
state = State.Alert;
|
||||
animator.speed = attackSpeedMultiplier;
|
||||
skillFinishedCallback?.Invoke();
|
||||
@@ -1232,6 +1246,10 @@ public class UnitBase : MonoBehaviour
|
||||
|
||||
if (!navAgent.isOnNavMesh) return;
|
||||
|
||||
// 追击时用正常速度和正常停靠距离(可能刚从回位状态切回来)
|
||||
navAgent.speed = speed;
|
||||
navAgent.stoppingDistance = NormalStoppingDistance;
|
||||
|
||||
// 确保没有被停止
|
||||
if (navAgent.isStopped)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: XX4b4Sj+VXxuxB9gb8yVHKpQYSGcJVjr5mzI4RA3uPKfov4bDCvQsZE=
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
After Width: | Height: | Size: 531 B |
@@ -0,0 +1,163 @@
|
||||
fileFormatVersion: 2
|
||||
guid: CyxKsCn+AClYPC7V7ifHiA+4oCDYo5bwTLVEuiEPllLn+zIihQs8LIs=
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 14
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
webStreaming: 0
|
||||
priorityLevel: 0
|
||||
uploadedMode: 2
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 20, y: 20, z: 20, w: 20}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WeixinMiniGame
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: PlayableAds
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
doOverrideTextureManagerOperations: 0
|
||||
platformOperationGroupSettings:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
After Width: | Height: | Size: 560 B |
@@ -0,0 +1,163 @@
|
||||
fileFormatVersion: 2
|
||||
guid: DisYsXz5AX2mNjLLKaPRDwUt6XTTaQB0eNQaPyYL9K5dwtl6j6Mi/u0=
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 14
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
webStreaming: 0
|
||||
priorityLevel: 0
|
||||
uploadedMode: 2
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 15, y: 15, z: 15, w: 15}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WeixinMiniGame
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: PlayableAds
|
||||
maxTextureSize: 2048
|
||||
maxPlaceholderSize: 32
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
doOverrideTextureManagerOperations: 0
|
||||
platformOperationGroupSettings:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -28,7 +28,8 @@
|
||||
- [2026-09-29 22:28:50] 英雄复活后不寻敌问题:需要在ReviveHero()中调用unitBase.ResetAnchorPosition()重置锚点位置,否则returnToAnchorWhenIdle=true的英雄会尝试返回旧锚点位置导致卡住
|
||||
- [2026-10-01 15:45:16] UnitBase动画速度问题:攻击时会设置animator.speed来调整攻击动画速度,但攻击结束后必须在Alert状态和ReturnToAnchor中重置为1.0,否则会导致后续移动动画变慢
|
||||
- [2026-10-01 15:45:27] 投射物方向问题:使用transform.Translate(Vector3.forward)的投射物必须在Instantiate时计算正确的旋转Quaternion.LookRotation(direction),否则会朝默认方向飞行。已在UnitBase.FireProjectile和FireSkillProjectile中修复
|
||||
- [2026-10-02 00:03:51] Do NOT manually instantiate stun VFX in skill scripts like StoneGolemSkill.cs — UnitBase.ApplyAreaStun() handles it internally when the prefab reference is set in Inspector. Keep skill scripts minimal: just call ApplyAreaSkillDamage and ApplyAreaStun
|
||||
- [2026-10-02 10:27:11] 石巨人地裂技能职责:命中帧实例化并调用 `ShockwaveRing.Play()` 播放地面扩散光圈;范围伤害与眩晕分开处理,`UnitBase.ApplyAreaStun()` 只给范围内每个敌方角色调用其自身 `StatusEffectController.ApplyStun()`,星星特效由角色状态组件生成、跟随和清理。石巨人不应直接实例化眩晕星星特效。
|
||||
|
||||
- [2026-10-02 00:03:51] UnitBase fields: use unit.Camp (property), unit.IsAlive (property), NOT unit.camp or unit.isAlive (do not exist). StatusEffectController is private — access stun logic through public UnitBase methods only
|
||||
|
||||
### Project
|
||||
@@ -122,6 +123,14 @@
|
||||
- [2026-10-01 22:57:06] UnitBase.IsWithinAttackReach 攻击缓冲:基础 buffer=0.2,攻击状态下再 +0.5 防状态抖动(UnitBase.cs 约530行)。buffer 过大会造成"隔空对打"——1.5 时近战实际在2.5米外就开打。
|
||||
- [2026-10-01 22:57:19] DefenseWaveLevelController 生成小怪时必须显式设置 UnitTeam.teamId=1(仅设 tag="Enemy" 不够),否则 Prefab 上默认 teamId=0 会让小怪被当成友军,双方都不交战。场景中该组件的 enemyPrefabs 列表需配 4 项:castle_blue_guard_q/castle_archer/castle_gold_guard/蓝角蛮卒。
|
||||
- [2026-10-02 00:03:51] Stone Golem stun VFX prefab path: Assets/Prefabs/特效/眩晕头顶星星/眩晕星星粒子.prefab — already exists, should be referenced in Stone Golem prefab Inspector for ApplyAreaStun to work
|
||||
- [2026-10-02 15:21:34] 2026-10-02 DefenseTest 人类士兵不移动的根因是 UnitBase 技能状态可能因 Animator 状态名不匹配而永久停在 State.Skill,导致 target=null、NavMeshAgent 无路径。UnitBase.PlaySkillAnimation/CheckSkillAnimationFinished 已加入技能超时兜底:动画正常结束或超过技能时长+缓冲都会恢复 Alert、清理回调并恢复 Animator 速度。
|
||||
- [2026-10-03 12:29:08] 2026-10-03 卡牌稀有度系统:CharacterData 有 CharacterRarity(Blue/Orange/Purple/Red),HeroCardUI 通过 BattleFormationSpawner 绑定 CharacterData 后选择对应边框;DefenseTest 五张卡片各有 RarityFrame Image,四种边框 Sprite 已绑定到 HeroCardUI 字段,RectTransform 保持卡片尺寸、可由用户自行调整。初始资源设定:荒野之王 Red;法师、狂暴狼人、盾卫、石巨人、精锐士兵、荒野祭司 Purple;其余现有角色 Blue;Orange 暂未分配。
|
||||
- [2026-10-03 23:38:14] DefenseTest场景已改造为开局布阵模式:玩家开局拖动英雄卡到3行6列后三排网格(BackZ=-15),点击开始战斗按钮后开始波次,每波结束英雄回到初始位置。不再预先配置阵容到JSON。已创建DefenseGameFlowController和GridLineVisualizer(红线可视化网格,Y=0.5)。StartBattleButton在BottomUI下。
|
||||
- [2026-10-04 09:28:04] 2026-10-04 DefenseTest 开局卡牌拖动修复完成:根本原因是 BattleFormationSpawner 在 Start() 时自动生成英雄(法师/弓箭手),DefenseGameFlowController.InitializeCardDrag() 需要的 HeroRoster.asset 因损坏无法加载。修复方案:1) 重新创建 HeroRoster.asset 包含5个英雄并正确设置 unitPrefab 引用;2) 在场景中禁用 BattleFormationSpawner 组件,塔防版不需要自动生成初始英雄;3) DefenseGameFlowController.roster 字段在场景中配置 HeroRoster 引用。现在开局场上无单位,5张卡片均可拖动,HeroCardDrag 组件和 CanvasGroup 已自动配置。
|
||||
- [2026-10-04 10:15:39] 2026-10-04 DefenseTest 布阵拖拽系统重做完成。DeployGrid 常量改为 6列×5行、ColStep=2.8、RowStep=3.0、BackZ=-9(旧值 -15 落在 NavMesh 之外,单位会卡住)。战场/部署网格 的30个格位由 DefenseGameFlowController.AlignGridCells 按命名「格位_行_列」自动摆到 DeployGrid 坐标,布阵阶段显示、开战隐藏。新增 DeployHighlight(绿=可放/红=已占用,公开 IsVisible/IsBlocked/ShownCell),HeroCardDrag 重写为「生成半透明英雄幽灵跟随指针 + 平面射线吸附格位」,DefenseGameFlowController 增加 Instance/IsDeployPhase/PlaceHeroFromCard/IsCellOccupied/IsCardPlaced/RemoveHeroAt,点击已放置英雄可撤回(Update 里 Physics.Raycast 命中 UnitBase)。场景新增 StartBattleButton(Canvas 根、bottom-center、y=360、圆角绿底),deploymentUI 必须保持 null——英雄卡面板战斗中要一直显示血量/复活。血条隐藏要操作 WorldHealthBar.Awake 生成的子物体 "WorldHealthBar",不是组件所在的对象。
|
||||
- [2026-10-04 11:15:47] 2026-10-04 DefenseTest 布阵区域改为 4×4 并与用户新建的 Plane 完全重合。DeployGrid 常量:Cols=4、Rows=4、ColStep=2.875、RowStep=2.8、BackZ=-14.2、CellWidth=2.815、CellDepth=2.74、GridY=0.115、UnitY=0.10(对齐重烘后的 NavMesh)。Plane 原在 y=0.5 会挡住单位,已降到 y=0.09 并放入 Buildings 层(layer 8)排除烘焙;NavMeshSurface 体积改为 center=(0,1,12) size=(28,12,62) 重烘,NavMesh 高度由 0.16 变 0.095,DefenseWaveLevelController.spawnY 同步改为 0.1。开始游戏按钮改为顶部居中(anchor 上中、anchoredPosition y=-170、420×120)。注意:BattlePlatform 实际只覆盖 Z -22.8..17.2,所以 NavMesh 远端也就到 ~16.9,敌人 spawnZ=20 本身在地面之外(靠 NavMeshAgent 自动吸附),这是既有行为。
|
||||
- [2026-10-04 13:12:11] 2026-10-04 英雄打完归位改为"走回去"(正常速度),去掉瞬移。关键坑:UnitBase.Start 里 `navAgent.stoppingDistance = attackRange*0.95` 会让 agent 在到达锚点前就认为"已到达"而停住(法师 5.7 米、盾卫 0.95 米都远大于 anchorArrivalDistance 0.35),所以"走回锚点"以前根本走不到——这正是当初只能瞬移的原因。修法:ReturnToAnchor 里把 stoppingDistance 设 0,RestoreIdleSpeed/move() 里恢复 NormalStoppingDistance。另新增 useAnchorLeash/anchorLeashDistance(英雄设为 10 米,DefenseGameFlowController.heroLeashDistance 控制),目标距锚点超过上限就不追,避免一路推到 Z≈16。DefenseGameFlowController.ResetHeroPositions 现在只清 target 让 UnitBase 自己走回,仅当 NavMesh.SamplePosition 找不到落脚点(真卡住)才瞬移兜底。
|
||||
- [2026-10-04 14:12:16] 2026-10-04 DefenseTest 两处修正:1) 阵位守护距离不再单开字段,直接用 UnitBase.detectionRange(已删除 anchorLeashDistance / heroLeashDistance;DefenseGameFlowController 只留开关 heroGuardPost=true,新 bool 字段在旧场景里会反序列化成 false,必须显式写进场景)。出战 5 个英雄 Prefab 的 detectionRange 已从 30/50 调到 10(弓箭手 12)。2) 底部英雄卡的角色改回从 PlayerData.json 的 currentDeck 读(站位不再读),卡面(头像/名字/稀有度)用同一份 CharacterData 刷新(新增 HeroCardUI.SetCharacterInfo,区别于绑定单位的 SetHero),否则会出现「卡面显示人类士兵、拖出来却是法师」的不一致;PlayerData 读不到时兜底用 HeroRoster。注意 CharacterData 里有些角色(荒野之王/荒野流寇等)unitPrefab 为空,不能出战,取阵容时要跳过。
|
||||
|
||||
### Reference
|
||||
- [2026-09-09 12:23:17] 飞行物脚本 Projectile.cs 负责锁敌追踪、碰撞检测和伤害结算。箭矢预制体 ArrowProjectile_White.prefab 已配置 Projectile 组件和 CapsuleCollider(Is Trigger)。远程单位需在攻击动画松弦帧添加 OnAttackEffect Event,并在 UnitBase 中设置 attackType=RangedProjectile、projectilePrefab、projectileSpawnPoint。
|
||||
@@ -4,6 +4,7 @@
|
||||
TagManager:
|
||||
serializedVersion: 2
|
||||
tags:
|
||||
- DeployGrid
|
||||
- Enemy
|
||||
- Friend
|
||||
- Building
|
||||
|
||||